如何防止webclient冻结程序

时间:2015-01-26 13:56:34

标签: c# webclient

目前我正在使用webclient从站点下载多个XML文件。但是在下载期间,团结一直冻结直到这些下载完成。这大概花了大约30秒,大部分时间都被内部编译器调用的waitforsecond()调用占用,导致12 * 2 1秒的等待调用。

有没有办法绕过这个/在另一个线程上运行它,但仍能从统一调用它?

 // the form is a login form
 public void PreObtainData(ref MonavisaRequestForm request, string dateAndTime, string fileDateAndTime)
    {
        if (!initialized)
            Initialize();
        try
        {
            if (!request.webclient.IsBusy && requestQueue.Count == 0)
            {
                request.url = request.url.Replace("&", "%26");
                request.url = request.url.Replace("+", "%2B");
                Uri uri = new Uri(string.Format("http://localhost/login.php?username={0}&password={1}&request={2}", request.username, request.password, request.url));
                request.webclient.DownloadFile(uri, @"Nioo Graph Data " + fileDateAndTime + ".xml");
            }
            else if (!request.webclient.IsBusy && requestQueue.Count > 0)
            {
                Uri uri = new Uri(string.Format("http://localhost/login.php?username={0}&password={1}&request={2}", requestQueue.Peek().username, requestQueue.Peek().password, requestQueue.Peek().url));
                requestQueue.Peek().webclient.DownloadFile(uri, @"Nioo Graph Data " + fileDateAndTime + ".xml");
                requestQueue.Dequeue();
            }
            else
            {
                requestQueue.Enqueue(request);
            }
        }
        catch (System.Net.WebException ex)
        {
            if (ex.Status != System.Net.WebExceptionStatus.ProtocolError)
            {
                throw;
            }
        }
    }

2 个答案:

答案 0 :(得分:3)

您应该使用DownloadFileTaskAsync之类的异步方法和DownloadFile关键字来确保在方法返回数据后继续处理,而不是像async/await那样使用阻塞方法:

 // the form is a login form
public async Task PreObtainData(ref MonavisaRequestForm request, string dateAndTime, string fileDateAndTime)
{
    if (!initialized)
        Initialize();
    try
    {
        if (!request.webclient.IsBusy && requestQueue.Count == 0)
        {

            ...
            await request.webclient.DownloadFileTaskAsync(uri, @"Nioo Graph Data " + fileDateAndTime + ".xml");
        }
        else if (!request.webclient.IsBusy && requestQueue.Count > 0)
        {
            ...
            await requestQueue.Peek().webclient.DownloadFileTaskAsync(uri, @"Nioo Graph Data " + fileDateAndTime + ".xml");
            requestQueue.Dequeue();
        }
        else
        {
            requestQueue.Enqueue(request);
        }
    }
    catch (System.Net.WebException ex)
    {
        if (ex.Status != System.Net.WebExceptionStatus.ProtocolError)
        {
            throw;
        }
    }
}

这也会将PreObtainData转换为异步方法。您应该修改其调用者以处理任务。如果在事件处理程序中调用此方法,可以通过将处理程序的签名更改为async void而不是void来完成此操作,例如:

private async voidForm1_Load(object sender, System.EventArgs e)
{
    ...
    await PreObtainData(...);
    ...
}

答案 1 :(得分:0)

Microsoft在System.ComponentModel命名空间中公开了一个BackgroundWorker类,该命名空间专门用于这些类型的操作。您所要做的就是在表单中添加后台工作程序,并捕获与其关联的DoWork和RunWorkerCompleted事件。您将在DoWork事件中执行下载,然后在RunWorkerCompleted事件中执行任何完成工作和/或清理。

正如@Panagiotis指出的那样,我不确定你的问题与Unity有什么关系,就像运行后台进程以防止主线程被锁定一样。试试BackgroundWorker,看看它是否能实现你的目标。