暂停/恢复异步任务的模式?

我有一个主要是IO绑定的连续任务(后台拼写检查器与拼写检查服务器通信)。 有时,此任务需要暂停并稍后恢复,具体取决于用户活动。

虽然暂停/恢复基本上是async/await所做的,但我发现很少有关于如何为异步方法实现实际暂停/播放逻辑的信息。 有推荐的模式吗?

我也考虑过使用Stephen Toub的AsyncManualResetEvent ,但认为这可能是一种矫枉过正。

考虑到当前代码的混乱程度, AsyncManualResetEvent正是您所需要的。 但是稍微好一点的解决方案是使用Stephen Toub的另一种方法: PauseToken 。 它的工作方式与AsyncManualResetEvent类似,不同之处在于它的接口专门用于此目的。

它对我有用

  using System; using System.Threading; using System.Threading.Tasks; namespace TaskTest2 { class Program { static ManualResetEvent mre = new ManualResetEvent(false); static void Main(string[] args) { mre.Set(); Task.Factory.StartNew(() => { while (true) { Console.WriteLine("________________"); mre.WaitOne(); } } ); Thread.Sleep(10000); mre.Reset(); Console.WriteLine("Task Paused"); Thread.Sleep(10000); Console.WriteLine("Task Will Resume After 1 Second"); Thread.Sleep(1000); mre.Set(); Thread.Sleep(10000); mre.Reset(); Console.WriteLine("Task Paused"); Console.Read(); } } } 

好吧,也许这值得一个答案,但我对C#并不熟悉,我在这里没有MonoDevelop,现在是凌晨3点,所以请怜悯。

我建议像这样的东西

 class Spellchecker { private CancellationTokenSource mustStop = null; private volatile Task currentTask = null; //TODO add other state variables as needed public void StartSpellchecker() { if (currentTask != null) { /* * A task is already running, * you can either throw an exception * or silently return */ } mustStop = new CancellationTokenSource(); currentTask = SpellcheckAsync(mustStop.Token); currentTask.Start(); } private async Task SpellcheckAsync(CancellationToken ct) { while (!ct.IsCancellationRequested)) { /* * TODO perform spell check * This method must be the only one accessing * the spellcheck-related state variables */ } currentTask = null; } public async Task StopSpellchecker() { if (currentTask == null) { /* * There is no task running * you can either throw an exception * or silently return */ } else { /* * A CancelAfter(TimeSpan) method * is also available, which might interest you */ mustStop.Cancel(); //Remove the following lines if you don't want to wait for the task to actually stop var task = currentTask; if (task != null) { await task; } } } }