异步任务暂停循环恢复

我有一个示例代码,取自MSDN,我想在while循环中实现Pause / Resumefunction。 任何人都可以提出一个解决方案/ parern吗?

private async void startButton_Click(object sender, RoutedEventArgs e) { resultsTextBox.Clear(); // Instantiate the CancellationTokenSource. cts = new CancellationTokenSource(); try { await AccessTheWebAsync(cts.Token); resultsTextBox.Text += "\r\nDownloads complete."; } catch (OperationCanceledException) { resultsTextBox.Text += "\r\nDownloads canceled.\r\n"; } catch (Exception) { resultsTextBox.Text += "\r\nDownloads failed.\r\n"; } cts = null; } private void cancelButton_Click(object sender, RoutedEventArgs e) { if (cts != null) { cts.Cancel(); } } async Task AccessTheWebAsync(CancellationToken ct) { HttpClient client = new HttpClient(); // Make a list of web addresses. List urlList = SetUpURLList(); // ***Create a query that, when executed, returns a collection of tasks. IEnumerable<Task> downloadTasksQuery = from url in urlList select ProcessURL(url, client, ct); // ***Use ToList to execute the query and start the tasks. List<Task> downloadTasks = downloadTasksQuery.ToList(); // ***Add a loop to process the tasks one at a time until none remain. while (downloadTasks.Count > 0) { // Identify the first task that completes. Task firstFinishedTask = await Task.WhenAny(downloadTasks); // ***Remove the selected task from the list so that you don't // process it more than once. downloadTasks.Remove(firstFinishedTask); // Await the completed task. int length = await firstFinishedTask; resultsTextBox.Text += String.Format("\r\nLength of the download: {0}", length); } } 

有一篇MSDN文章使用PauseToken解决了这个PauseToken (类似于CancellationToken )。

以下是该文章中演示此概念的示例代码:

 namespace PauseTokenTestApp { public class PauseTokenSource { private volatile TaskCompletionSource m_paused; internal static readonly Task s_completedTask = Task.FromResult(true); public bool IsPaused { get { return m_paused != null; } set { if (value) { Interlocked.CompareExchange( ref m_paused, new TaskCompletionSource(), null); } else { while (true) { var tcs = m_paused; if (tcs == null) return; if (Interlocked.CompareExchange(ref m_paused, null, tcs) == tcs) { tcs.SetResult(true); break; } } } } } public PauseToken Token { get { return new PauseToken(this); } } internal Task WaitWhilePausedAsync() { var cur = m_paused; return cur != null ? cur.Task : s_completedTask; } } public struct PauseToken { private readonly PauseTokenSource m_source; internal PauseToken(PauseTokenSource source) { m_source = source; } public bool IsPaused { get { return m_source != null && m_source.IsPaused; } } public Task WaitWhilePausedAsync() { return IsPaused ? m_source.WaitWhilePausedAsync() : PauseTokenSource.s_completedTask; } } class Program { static void Main() { var pts = new PauseTokenSource(); Task.Run(() => { while (true) { Console.ReadLine(); pts.IsPaused = !pts.IsPaused; } }); SomeMethodAsync(pts.Token).Wait(); } public static async Task SomeMethodAsync(PauseToken pause) { for (int i = 0; i < 100; i++) { Console.WriteLine(i); await Task.Delay(100); await pause.WaitWhilePausedAsync(); } } } }