【问题标题】:Using Httprequest to get pictures from given URL使用 Httprequest 从给定的 URL 获取图片
【发布时间】:2011-06-01 21:36:03
【问题描述】:

我正在尝试从网络摄像头获取图片。有一个 php-python 网络服务可以从网络摄像头中获取图片并提供服务:它提供图片的服务类似于 http://ip/jpeg/camera=1

private HttpWebRequest request;
private HttpWebResponse response;
private CookieContainer container;
private Uri uri;
private string _user;
private string _pass;
private string _ip;
//Login code as seen in the previous section should be here
//GetImages is meant to run as a separate thread 
private void GetImages(string camNo)
{
//create the GET request for the JPEG snapshot (found at /jpeg on the IP Camera)
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://" + deviceIP + "/jpeg/camera"+camNo);
request.Method = "GET";
request.ContentType = "application/x-www-form-urlencoded";
request.CookieContainer = container;

//attempt to get a response from the IP110, event if error

try
{
    response = (HttpWebResponse)request.GetResponse();
}
catch (WebException e)
{
    ConnectionError(new ConnectionErrorEventArgs(e.Message));
}

//Get the stream containing the JPEG image.
Stream stream = response.GetResponseStream();

//Read the stream to memory.
byte[] buffer = new byte[100000];
int read, total = 0;

while ((read = stream.Read(buffer, total, 1000)) != 0)
{
    total += read;
}

//create a BMP image from the stream
Bitmap bmp = (Bitmap)Bitmap.FromStream(new MemoryStream(buffer, 0, total));

//send the bmp image to where you would like to display it. 
 }

...然后我将该位图作为 jpeg 存储到文件夹中。我的问题从这里开始;我想尽快完成这个过程。我想使用该代码从 50 个网络摄像头拍摄照片并以 jpeg 格式存储,而且它必须很快 - 我的意思是每 10 秒我必须从 50 个摄像头获取新照片。

我使用了 timercontrol,每 500ms 给它 500ms 程序使用上面的代码到相机 编号并保存jpeg,但它一个接一个地工作,所以性能变低了!

50ms x 500cams = 25000 ms (25sec),如果我安排定时器控制的间隔 100 ms 程序冻结。 当我使用上面的代码时,我会在 200 毫秒内得到位图 bmp,但是当它尝试在磁盘上写入 jpeg 时需要很长时间。

我可以做些什么来更快地写入磁盘?我寻找内存映射 - 有帮助吗?我想将 jpeg 存储在光盘上,因为我将在网站上提供这些图片并与人们分享。我可以使用内存映射并通过网站公开提供它吗?

更新: 我还使用 WebClient 类进行异步工作, http://www.informit.com/guides/content.aspx?g=dotnet&seqNum=571

结果是:得到一张 300 毫秒左右的图片并将其写入磁盘大约 700 毫秒 所以我必须找到一个尽可能多地写入磁盘的解决方案。

哪个更好?将图片写入磁盘或将图像发送到数据库? 我试图存储图片以使其准备好服务,因为在网站上人们必须看到更新的图片。哪一个更适合成千上万的客户查询?将它们存储在磁盘上还是以二进制形式存储在数据库中?

【问题讨论】:

  • 这是网络吗?桌面?手机?
  • 它是桌面应用程序,python-php 服务为它们提供服务,在同一台机器上我尝试使用上面的代码获取图片。

标签: c# performance get httprequest image


【解决方案1】:

获取图像的代码是同步的。我建议修改您的代码以使用HttpWebRequest.BeginGetResponse() 来获取您的图像,如this answer 中所述。

因此,当您的(单个)计时器触发时,开始向您的摄像头发送异步请求,然后(当它们完成时)回调将针对每个完成的请求触发,您可以保存返回的图像。

如果您需要进一步优化,则可以将图像保存到磁盘委托给后台ThreadPool work item

【讨论】:

  • 你知道我之前尝试过什么,我制作了 Timer[] 数组,如果有 50 个摄像头,Timer 数组长度为 50,所以当计时器滴答时,该代码异步工作,同时从相机拍照,但是性能太低了,当我查看存储的图片时,它被冻结了,无法刷新。你的答案可以成为我的解决方案吗?你认为呢?谢谢
  • 是的,您最好按照@arcain 的建议使用 BeginGetResponse()。计时器的问题取决于您选择的计时器类型,您在 UI 线程上运行它们并锁定 UI。此外,您最好添加到@arcain 的建议中,并在异步调用中分层以进行流读取,因为这可能是最耗时的部分。
  • 我认为 webclient 类已经有了异步进程的方法。我使用了它,它的工作原理和我认为比 Httprequest 更快,还有一个问题我怎样才能尽可能多地写入磁盘?
【解决方案2】:

任何时候您需要比堆叠响应更快地获得响应,您最终不得不使用多个线程一次完成多项工作(最后一句话是这里的线索)。

在 .NET 中,这意味着要么设置你自己的线程库,要么使用 TPL,等等。

添加:正如下面的评论所指出的,这可能意味着使用异步调用并允许框架为您隐式创建线程,而不是自己控制它们。事实上,您可以使用线程池,但仍然可以选择异步或同步,而无需控制创建的线程数。如果您真的想深入了解,您甚至可以使用操作系统级别的中断处理程序将线程卸载到操作系统(Ruby 使用的一种方法,例如,在 1.9 之前,它引入了“真正的”线程而不是“绿色”线程 - 是的,TMI)。

如果您有 2 分钟的工作时间和 30 秒的时间完成工作,答案仍然有效,您需要一个多线程解决方案,无论您是否知道您实际上是线程化(显式创建)(由框架/操作系统处理的隐式创建)。

【讨论】:

  • 事实上我对TPL一无所知,你和@arcain有什么关系
  • -1 “设置你自己的线程库”真的吗?所以.NET 与此无关?那么BeginMETHOD 是什么? .NET 对几乎所有重要的方法都有异步调用,只需使用它们!
  • @balexandre:所以我错过了一点,因为我没有说明“通过异步调用使用隐式线程”。这是一个相当笼统的陈述,而且是正确的,尽管没有你想的那么冗长。我编辑它只是为了取悦你。 ;-)
猜你喜欢
  • 2012-11-01
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 2019-02-20
  • 1970-01-01
  • 2012-08-05
  • 2012-01-04
  • 1970-01-01
相关资源
最近更新 更多