我是C#中的新手,我遇到了一个我不会受到影响的问题。在下面的代码中,有人可以解释为什么Unsubscribe方法结束时的WriteLine永远不会被调用。它似乎与前面的foreach循环中的ContinueWith有关,好像我评论它的工作正常。 感谢
using System;
using System.Threading;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
public class Example
{
public static void Main()
{
Task.Run(() => Unsubscribe());
Console.WriteLine("Method: Main. End");
Console.ReadKey();
}
private static void Unsubscribe()
{
Dictionary<int, string> dicPairsBySubID = new Dictionary<int, string>();
dicPairsBySubID.Add(1, "A");
dicPairsBySubID.Add(2, "B");
dicPairsBySubID.Add(3, "C");
dicPairsBySubID.Add(4, "D");
dicPairsBySubID.Add(5, "E");
List<Task> taskList = new List<Task>();
foreach (KeyValuePair<int, string> sub in dicPairsBySubID)
{
int chanID = sub.Key;
Task task = Task.Run(() => SendUnsubscribe(chanID))
.ContinueWith(tsk =>
{
var flattened = tsk.Exception.Flatten();
flattened.Handle(ex =>
{
Console.WriteLine(string.Format("Error unsubscribing pair {0} (chanID = {2})", sub.Value, chanID), ex);
return true;
});
}, TaskContinuationOptions.OnlyOnFaulted);
taskList.Add(task);
}
Task.WhenAll(taskList).Wait();
// WHY DOES THIS NEVER GET RUN?
Console.WriteLine("Method: Unsubscribe. End");
}
private static async Task SendUnsubscribe(int chanID)
{
await SendAsync(chanID);
Console.WriteLine("Method: SendUnsubscribe. Chan ID: " + chanID);
}
private static async Task SendAsync(int chanID)
{
await Task.Run(() => Thread.Sleep(1000));
Console.WriteLine("Method: SendAsync. Chan ID: " + chanID);
}
}
答案 0 :(得分:2)
您的任务会抛出一个您没有捕获的异常,因为:
ContinueWith
也会返回一个任务(然后放在taskList
)TaskContinuationOptions.OnlyOnFaulted
)Cancelled
Task.Run(() => Unsubscribe())
调用的返回值不是await
,因此永远不会被注意到。继续:
您不应在任务上使用Wait()
。您已经开始使用async
和await
,通过您的计划使用它。
真正使用Wait()
的唯一原因是你当然不能使用异步。尽量避免它。
当Async
为async
时,请始终使用后缀multiDexEnabled = true
命名。这显示了使用该方法的用户的明确意图。
答案 1 :(得分:1)
我测试了这个。我在 var labelText = $("#label1").text();
if (!labelText) {
$("#div1").show();
}
处收到异常,说任务已取消。这使得所有这一切都有意义:
WhenAll
任务添加到ContinueWith
。taskList
任务被取消,因为它应该运行ContinueWith
,并且没有发生异常。OnlyOnFaulted
的其余部分未运行。您可以采取以下措施来改善这一点:
不要使用Task.Run来运行异步方法。你可以这样做:
Unsubscribe
在taskList.Add(SendUnsubscribe(chanID));
方法中使用try
/ catch
,而不是在任务中使用SendUnsubscribe
。
等待ContinueWith
而非使用WhenAll
:
Wait()
如果您认为await Task.WhenAll(taskList);
无法处理任何例外情况,您始终可以将await Task.WhenAll(taskList);
包裹在try
/ catch
区块中。