异步任务暂停环路简历 [英] Async Tasks Pause Resume of Loop

查看:114
本文介绍了异步任务暂停环路简历的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个样品code,从MSDN拍摄,我想实现while循环中的暂停/恢复功能。任何人可以提出一个解决方案/ parern这将喊得呢?

 专用异步无效startButton_Click(对象发件人,RoutedEventArgs E)
    {
        resultsTextBox.Clear();        //实例化CancellationTokenSource。
        CTS =新CancellationTokenSource();        尝试
        {
            等待AccessTheWebAsync(cts.Token);
            resultsTextBox.Text + =\\ r \\ nDownloads完整的。
        }
        赶上(OperationCanceledException)
        {
            resultsTextBox.Text + =\\ r \\ nDownloads取消\\ r \\ n;
        }
        赶上(例外)
        {
            resultsTextBox.Text + =\\ r \\ nDownloads失败\\ r \\ n;
        }        CTS = NULL;
    }
    私人无效cancelButton_Click(对象发件人,RoutedEventArgs E)
    {
        如果(CTS!= NULL)
        {
            cts.Cancel();
        }
    }
    异步任务AccessTheWebAsync(CT的CancellationToken)
    {
        HttpClient的客户端=新的HttpClient();        //使Web地址的列表。
        清单<串GT; urlList = SetUpURLList();        // ***创建查询,在执行时,返回的任务集合。
        IEnumerable的<任务< INT>> downloadTasksQuery =
            从urlList URL选择ProcessURL(URL,客户端,CT);        // ***用了ToList执行查询并启动任务。
        清单<任务< INT>> downloadTasks = downloadTasksQuery.ToList();        // ***添加一个循环来处理的任务之一在一个时间,直到没有剩余。
        而(downloadTasks.Count大于0)
        {
                //标识完成了第一个任务。
                任务< INT> firstFinishedTask =等待Task.WhenAny(downloadTasks);                // ***从列表中删除所选的任务,这样你不
                //过程中,它超过一次。
                downloadTasks.Remove(firstFinishedTask);                //等待完成的任务。
                INT长度=等待firstFinishedTask;
                resultsTextBox.Text + =的String.Format(下载的\\ r \\ nLength:{0},长度);
        }
    }


解决方案

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

下面是从本文的示例code演示了这一概念:

 命名空间PauseTokenTestApp
{
    公共类PauseTokenSource
    {
        私人挥发性TaskCompletionSource<布尔> m_paused;
        内部静态只读任务s_completedTask = Task.FromResult(真);        公共BOOL isPaused得到
        {
            {返回m_paused!= NULL; }
            组
            {
                如果(值)
                {
                    Interlocked.CompareExchange(
                        REF m_paused,新TaskCompletionSource<布尔>(),NULL);
                }
                其他
                {
                    而(真)
                    {
                        VAR TCS = m_paused;
                        如果(TCS == NULL)回报;
                        如果(Interlocked.CompareExchange(REF m_paused,空,TCS)== TCS)
                        {
                            tcs.SetResult(真);
                            打破;
                        }
                    }
                }
            }
        }
        公共PauseToken令牌{{返回新PauseToken(本); }}        内部任务WaitWhilePausedAsync()
        {
            VAR CUR = m_paused;
            返回恶狗!= NULL? cur.Task:s_completedTask;
        }
    }    公共结构Paus​​eToken
    {
        私人只读PauseTokenSource m_source;
        内部PauseToken(PauseTokenSource源){m_source =来源; }        公共BOOL isPaused得到{{返回m_source = NULL&放大器;!&安培; m_source.IsPaused; }}        公共任务WaitWhilePausedAsync()
        {
            返回isPaused得到?
                m_source.WaitWhilePausedAsync():
                PauseTokenSource.s_completedTask;
        }
    }    类节目
    {
        静态无效的主要()
        {
            VAR点=新PauseTokenSource();
            Task.Run(()=>
            {
                而(真)
                {
                    到Console.ReadLine();
                    !pts.IsPaused = pts.IsPaused;
                }
            });
            SomeMethodAsync(pts.Token).Wait();
        }        公共静态异步任务SomeMethodAsync(PauseToken暂停)
        {
            的for(int i = 0; I< 100;我++)
            {
                Console.WriteLine(ⅰ);
                等待Task.Delay(100);
                等待pause.WaitWhilePausedAsync();
            }
        }
    }
}

I have a sample code, taken from MSDN, to which I would like implement the Pause / Resume functionality within while loop. Could anybody propose a solution / parern which would hande this?

 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<string> urlList = SetUpURLList();

        // ***Create a query that, when executed, returns a collection of tasks.
        IEnumerable<Task<int>> downloadTasksQuery =
            from url in urlList select ProcessURL(url, client, ct);

        // ***Use ToList to execute the query and start the tasks. 
        List<Task<int>> 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<int> 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);
        }
    }

解决方案

There is an MSDN article that solves this using a PauseToken (similar to a CancellationToken).

Here's the sample code from that article that demonstrates this concept:

namespace PauseTokenTestApp
{
    public class PauseTokenSource
    {
        private volatile TaskCompletionSource<bool> 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<bool>(), 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();
            }
        }
    }
}

这篇关于异步任务暂停环路简历的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆