【问题标题】:How to Pause and Resume the Task which runs Asynchronously如何暂停和恢复异步运行的任务
【发布时间】:2016-04-05 07:09:52
【问题描述】:

我有一个长时间运行的代码,我想要暂停恢复功能。在 start 方法中,我正在编写我的代码并启动新的异步任务。但我希望按需暂停/恢复此任务。

  var myTask;
  public void start()
    {
        myTask = Task.Factory.StartNew(() =>
        {
         ///my business logic
        });
    }

【问题讨论】:

  • 你的代码是在循环还是什么?
  • 任务调度是协作的。要暂停任务,您需要使用某种方式与它沟通;例如,通过设置哨兵标志。但是,观察和尊重国旗将取决于任务。如果你想要抢占式调度(你可以强制一个暂停),你需要恢复到线程。请注意,即使线程在执行本机调用时也不能暂停。
  • 向最优秀的人学习。这是 Stephen Toub 对这个问题的看法:blogs.msdn.com/b/pfxteam/archive/2013/01/13/…
  • 我很困惑,你标记了这个 C# 4.0,还标记了 async-await,这是 C# 5.0 的一个特性。那么它是什么?
  • sorry svick (: 它不是 async-await,只是 C# 4.0 TPL 特性

标签: .net c#-4.0 asynchronous async-await


【解决方案1】:

您必须了解任务和线程之间的区别。任务是您想要完成的事情。线程是执行该任务的许多可能的工作人员之一。单独的任务不必由单独的线程执行。同一个线程可以执行多个任务。一项任务可能由多个线程执行。

如果您想要某种级别的控制,希望能够在任何时候暂停正在运行的任务一段时间,无论它现在正在做什么,请考虑使用线程。请注意,当您暂停线程一段时间后,它会占用当时可能使用的稀缺资源。

因此,仅将流程保持在某些预定义的执行点可能更明智。在这种情况下,Task 可能是更明智的选择。

通过使用一个任务,你表示你不想被谁在执行,因此你无法控制刽子手。事实上,通过使用一项任务,您甚至可以表示您甚至不在乎您的整个过程是由一个线程还是由多个线程处理的。

如果您想在流程中的某些定义点停止流程的执行,请考虑将任务划分为子任务,每个子任务在您希望流程停止的点结束。通过使用 Task.ContinueWith,您可以决定任务何时应继续处理流程的下一步。

简洁的解决方案是将您的流程(或任务)包装到一个类中,该类的用户可以说:运行直到执行步骤 X,或者:运行直到达到状态 Y。这样,该类的用户甚至不必知道您的进程是使用任务还是线程运行。

【讨论】:

  • 您能否提供一个线程 API 示例,该示例能够“在任何时候暂停正在运行的任务,无论它现在正在做什么”?
  • @KirillShlenskiy System.Threading.Thread.Suspend(),但是该方法已被标记为已过时,它确实建议您使用另一种放置“检查点”的方法,您可以在其中使用信号量、互斥锁或其他一些方法暂停执行逻辑。
  • 我非常同意:任何时候都不要暂停。你不知道线程在做什么,在你挂起的那一刻,所以你不能确定允许挂起者做什么。此外,我想知道是否真的有必要立即停止其他任务。
【解决方案2】:

好吧,您可以创建自己的简单任务调度程序,并从任务内部反复检查当前任务状态。为了使其线程安全,我们需要将布尔标志标记为volatile

class MySimpleTaskScheduler
{
   private volatile bool isPaused;
   private volatile bool isStopped;
   private Task _myBackgroundTask;

   public void StartTask()
   {
       _myBackgroundTask = new Task.Run(() => 
       {
          while(!isStopped)
          {
             while(!isPaused && !isStopped)
             {
                .. do something
                Thread.Sleep(100);  // set some delay before check if task is set on pause
             }

             Thread.Sleep(100);  // set some timeout before check if task is stopped              }
       });
   }

   public void Pause()
   {
      isPaused = true;     
   }

   public void Resume()
   {
      isPaused = false;         
   }

   public void Stop()
   {
      isPaused = true;       
      isStopped = true;       
   }
} 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2020-07-25
    • 2021-12-17
    • 2016-08-26
    • 2017-01-27
    相关资源
    最近更新 更多