【发布时间】:2018-01-18 16:38:15
【问题描述】:
我是 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);
}
}
【问题讨论】:
-
如果您要使用异步,请正确使用。使用带有
async main的 C# 7.1。不要使用.ContinueWith()或.Wait()。这些是代码气味。您需要await异步调用。阅读Async/Await - Best Practices in Asynchronous Programming。 -
您不需要所有这些
Task.Runs。特别是,当 SendUnsubscribe 已经是一个任务并且甚至不等待它的结果或异常时,将它包装在一个中的意义何在?Task.WhenAll(taskList).Wait();也可以替换为await Task.WhenAll(taskList);声明private async Task Unsubscribe()。
标签: c# multithreading task task-parallel-library