【发布时间】:2014-03-04 07:19:46
【问题描述】:
这是关于 .NET 4.0
我正在尝试使用 Task 从多个 WebAPI 异步获取数据。在控制台应用程序中,程序运行良好,但是当我创建 Web 应用程序时,任务的状态总是卡在“WaitingForActivation”。任何帮助将不胜感激。以下是我的一段代码:
public String[] CallClientAPI(string[] addresses)
{
CancellationTokenSource cts = new CancellationTokenSource();
int timeToWait = 3000; //wait for 3 seconds to fetch API Data
Task.Factory.StartNew(() =>
{
Thread.Sleep(timeToWait);
cts.Cancel();
});
Task<String[]> webTask = GetAPIData(addresses, cts.Token);
//webTask is always in "WaitingForActivation" mode only ..
if (!webTask.IsCompleted)
{
Thread.SpinWait(5000000);
}
String[] results = null;
try
{
results = webTask.Result;
}
catch
{
}
//other code
}
编辑:
--------GetAPIData 的代码--------
public Task<string[]> GetAPIData(String[] urls, CancellationToken token)
{
TaskCompletionSource<string[]> tcs = new TaskCompletionSource<string[]>();
WebClient[] webClients = new WebClient[urls.Length];
token.Register(() =>
{
foreach (var wc in webClients)
{
if (wc != null)
wc.CancelAsync();
}
});
object m_lock = new object();
int count = 0;
List<string> results = new List<string>();
for (int i = 0; i < urls.Length; i++)
{
webClients[i] = new WebClient();
webClients[i].DownloadStringCompleted += (obj, args) =>
{
if (args.Cancelled == true)
{
tcs.TrySetCanceled();
return;
}
else if (args.Error != null)
{
tcs.TrySetException(args.Error);
return;
}
else
{
results.Add(args.Result);
}
lock (m_lock)
{
count++;
if (count == urls.Length)
{
tcs.TrySetResult(results.ToArray());
}
}
};
Uri address = null;
try
{
address = new Uri(urls[i]);
webClients[i].DownloadStringAsync(address, address);
}
catch (UriFormatException ex)
{
tcs.TrySetException(ex);
return tcs.Task;
}
}
return tcs.Task;
}
【问题讨论】:
-
天啊
Thread.SpinWait(5000000);?你确定你在做什么? -
这只是一个复制粘贴..我也尝试将这一行注释掉。但是同样的“WaitingForActivation”占了上风:(
-
和
GetAPIData的代码? -
对我来说看起来不错,当
DownloadStringCompleted触发并完成所有任务时,任务状态最终应该会改变。 -
但它没有......也许我可能遗漏了一些东西......不过这在控制台应用程序中工作正常。
标签: .net c#-4.0 asynchronous task-parallel-library