2016-04-05 9 views
1

Ich habe einen langen laufenden Code, den ich Pause fortsetzen möchte. In der Start-Methode schreibe ich meinen Code und starte die neue Async-Aufgabe. Aber ich möchte, dass diese Aufgabe bei Bedarf angehalten/fortgesetzt wird.Wie pausiere ich und setze die Aufgabe fort, die asynchron läuft

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

Ist Ihr Code eine Schleife oder etwas zu tun? –

+3

Aufgabenplanung ist kooperativ. Um eine Aufgabe anzuhalten, müssen Sie einige Mittel verwenden, um dies zu kommunizieren. zum Beispiel durch Setzen eines Sentinel-Flags. Es wird jedoch Aufgabe sein, die Flagge zu beobachten und zu ehren. Wenn Sie eine vorbeugende Planung (wo Sie eine Pause erzwingen können) möchten, müssen Sie zu Threads zurückkehren. Beachten Sie, dass sogar Threads nicht pausiert werden können, wenn sie native Aufrufe ausführen. – Douglas

+1

Lernen Sie von den Besten. Hier ist Stephen Toub das Problem zu nehmen: http://blogs.msdn.com/b/pfxteam/archive/2013/01/13/cooperativa-pausing-async-methods.aspx –

Antwort

3

Sie müssen sich der Unterschiede zwischen einer Aufgabe und einem Thread bewusst sein. Eine Aufgabe ist etwas, was Sie tun möchten. Ein Thread ist einer der vielen möglichen Arbeiter, die diese Aufgabe ausführen. Separate Aufgaben müssen nicht von separaten Threads ausgeführt werden. Derselbe Thread kann mehrere Aufgaben ausführen. Eine Aufgabe kann von mehreren Threads ausgeführt werden.

Wenn Sie ein Maß an Kontrolle wollen, wo Sie in der Lage sein wollen, jederzeit eine laufende Aufgabe für eine Weile zu stoppen, unabhängig davon, was es jetzt tut, sollten Sie einen Faden. Seien Sie sich bewusst, dass wenn Sie einen Thread für eine Weile anhalten, er die knappen Ressourcen, die er in diesem Moment benutzen könnte, halten wird.

Daher könnte es sinnvoller sein, Ihren Prozess nur an bestimmten vordefinierten Punkten der Ausführung zu halten. In diesem Fall könnte eine Aufgabe eine klügere Wahl sein.

durch eine Task mit euch sagen, dass Sie nicht wollen, mit belästigt werden, die die Ausführung tut, darum können Sie nicht den Henker steuern. Wenn Sie eine Aufgabe verwenden, drücken Sie sogar aus, dass es Ihnen sogar egal ist, ob Ihr vollständiger Prozess von einem oder mehreren Threads bearbeitet wird.

Wenn Sie die Ausführung Ihres Prozesses an bestimmten definierten Punkten im Prozess anhalten möchten, sollten Sie die Aufgabe in Unteraufgaben aufteilen, wobei jede Unteraufgabe an einem Punkt endet, an dem der Prozess angehalten werden soll. Wenn Sie Task.ContinueWith verwenden, können Sie entscheiden, wann die Task mit der Verarbeitung des nächsten Schritts des Prozesses fortfahren soll.

Die saubere Lösung wäre, Ihren Prozess (oder Aufgabe) in eine Klasse zu verpacken, wo Benutzer der Klasse sagen könnten: run, bis Schritt X ausgeführt wird, oder: run, bis Zustand Y erreicht ist. Auf diese Weise müssen die Benutzer der Klasse nicht einmal wissen, ob Ihr Prozess mit einer Aufgabe oder einem Thread ausgeführt wird.

+0

Können Sie ein Beispiel für eine Thread-API bereitstellen, die "eine laufende Aufgabe für eine Weile jederzeit anhalten kann, egal was sie gerade macht" bitte? –

+0

@KirillShlenskiy ['System.Threading.Thread.Suspend()'] (https://msdn.microsoft.com/en-us/library/system.threading.thread.suspend (v = vs.110). aspx), aber diese Methode wird als obsolet gekennzeichnet und es empfiehlt sich wirklich, die andere Methode zu verwenden, um "Checkpoints" zu setzen, wo Sie die Ausführung mit Semaphore, Mutex oder einer anderen Logik anhalten können. –

+0

Ich stimme zu: suspend nicht jeder Zeit.Du weißt nicht, was der Thread macht, in dem Moment, in dem du ihn ausschaltest, also kannst du dir nicht sicher sein, was der Träger tun darf. Außerdem frage ich mich, ob es wirklich notwendig ist, die andere Aufgabe sofort zu stoppen. –

0

Nun können Sie Ihren eigenen einfachen Taskplaner erstellen und innerhalb der Task wiederholt den aktuellen Taskstatus überprüfen. Um es fädeln sicher wir unsere Bool Flaggen markieren als volatile müssen (es bedeutet, dass sie denselben Wert für alle Threads haben werden):

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;  
    } 
} 
Verwandte Themen