创造一个等待冷酷的任务

Ewa*_*wan 9 c# task-parallel-library async-await

我完成后有一个异步方法,我想运行另一个方法.如果我只是调用方法并添加.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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

start task
end test
Complete
Run Code Online (Sandbox Code Playgroud)

预期产量:

start task
end task
Complete
end test
Run Code Online (Sandbox Code Playgroud)

更新:似乎没有办法创建一个不会立即在Task.Start上立即启动或完成的新任务?

Pet*_*ger 9

你的代表是异步无效的.async void-methods是火与遗忘.

参见模式和反模式摘要的第一点:http://rarcher.azurewebsites.net/Post/PostContent/31

也许你可以这样做:

[TestFixture]
public class FIXTURENAMETests {
  [Test]
  public async Task NAME() {
    var tcs = new TaskCompletionSource<bool>();
    Task t = LongRunningStuff(tcs);

    if (CanInsertInDictionary(t)) {
      tcs.SetResult(true);
    } else {
      tcs.SetException(new Exception());
    }

    Trace.WriteLine("waiting for end");

    try {
      await t;
    }
    catch (Exception exception) {
      Trace.WriteLine(exception);
    }

    Trace.WriteLine("end all");
  }

  private bool CanInsertInDictionary(Task task) {
    return true;
  }

  private async Task LongRunningStuff(TaskCompletionSource<bool> tcs) {
    Trace.WriteLine("start");
    try {
      await tcs.Task;
    }
    catch (Exception) {
      return;
    }
    Trace.WriteLine("do long running stuff");
    await Task.Delay(10000);
    Trace.WriteLine("end");
  }
}
Run Code Online (Sandbox Code Playgroud)