目前我正在使用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;
}
}
}
答案 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,看看它是否能实现你的目标。