【发布时间】:2015-04-23 13:35:50
【问题描述】:
我有一个异步方法,完成后我希望运行另一个方法。如果我简单地调用该方法并添加 .ContinueWith()
,这很好用但是,我有一个新要求,即只有在我能够将任务添加到并发字典时才开始任务。
我希望构建任务,尝试添加它然后启动任务
但是,Task.Start() 似乎立即完成了导致继续操作运行的任务,并且任何等待......而不是等待。
谁能解释为什么会发生这种情况以及实现我的目标的正确方法?
namespace UnitTestProject2
{
[TestClass]
public class taskProblem
{
[TestMethod]
public void Test()
{
CancellationTokenSource cancel = new CancellationTokenSource();
ConcurrentDictionary<Guid, Task> tasks = new ConcurrentDictionary<Guid,Task>();
Guid id = Guid.NewGuid();
Task t = new Task(async () => await Get(), cancel.Token);
t.ContinueWith(Complete);
if (tasks.TryAdd(id, t))
{
t.Start();
}
else
{
//another thread is stopping stuff dont start new tasks
}
t.Wait(); //expected to wait for the get function to complete
Console.WriteLine("end test");
}
public async Task Get()
{
Console.WriteLine("start task");
await Task.Delay(10000);
Console.WriteLine("end task");
}
public void Complete(Task t)
{
Console.WriteLine("Complete");
}
}
}
输出:
start task
end test
Complete
预期输出:
start task
end task
Complete
end test
更新:似乎没有办法创建一个不会立即在 Task.Start 上立即启动或完成的新任务?
【问题讨论】:
-
您要解决的真正问题是什么?该要求没有任何意义,并且将任务包装两层深也无济于事。创建冷任务并致电
Start是从不的充分理由。此外,没有理由包装Get,它已经在另一个任务中返回了正在运行的任务。只需写Task t=Get();。至于要求,没有意义。您始终可以将新项目添加到并发字典中,因为您实际上是在为其创建新的 Guid 键。 -
看起来您将异步委托传递给
Task构造函数,它不会等待从Get返回的任务完成。你为什么要在另一个任务中包装对Get的调用? -
真正的应用程序从队列发送推送通知,并有一个 Stop() 方法(从另一个线程调用)来停止启动新任务。在这种情况下,我需要未启动的任务,因此我可以以线程安全的方式将其添加到并发字典中。显然还有其他方法可以做到这一点,如果我无法解决这个问题,我将不得不使用这些方法
-
也是第一个应该被取消令牌取消的任务,而不是第二个
标签: c# async-await task-parallel-library