zoukankan      html  css  js  c++  java
  • 与循环有关的后台线程使用

    假定需要按顺序处理一系统工作,它们可能消耗较多时间,GUI线程期望获取每件工作的结果并予显示,同时处理掉异常而不是中断整体工作,比如使用同一个Http接口以上传文件,并发访问将会报错。

    常规做法是使用一个后台线程,线程遍历工作集合,并把结果POST到主线程,逻辑如下:

    AsyncOperation asyncOperation = null;

    private void button1_Click(object sender, EventArgs e)
    {
        asyncOperation = AsyncOperationManager.CreateOperation(null);
        Thread thread = new Thread(loopWork);
        thread.IsBackground = true;
        List<int> arr = Enumerable.Range(0, 10).ToList();
        thread.Start(arr);
    }

    private void loopWork(object obj)
    {
        List<int> arr = obj as List<int>;
        foreach (var item in arr)
        {
            try
            {
                string result = doWork(item);    //do some job
                asyncOperation.Post(showResult, result); //show result
            }
            catch (Exception ex)
            {
                asyncOperation.Post(showError, ex.ToString());    //handle error
            }
        }
    }

    doWork、showResult、showError等方法不再列出。这些方法都是接收object类型参数的void类型(即Action<object>)委托的实例,示例使用AsyncOperation.Post()方法实质上使用了Form窗体的同步上下文,更多内容请查阅CSDN。

    Task引入后任务调度器TaskScheduler的使用,同样是对同步上下文的使用,结果返回与异常处理不再分散到类的各种方法,避免了各种装箱拆箱。此例需求复杂了点,实现如下:

    private void button2_Click(object sender, EventArgs e)
    {
        var task = new Task(() => { });
        ConcurrentQueue<int> queue = new ConcurrentQueue<int>(Enumerable.Range(0, 10));
        while (!queue.IsEmpty)
        {
            int item;
            if (queue.TryDequeue(out item))
            {
                task.ContinueWith(t => doWork(item), TaskContinuationOptions.ExecuteSynchronously)
                    .ContinueWith(t =>
                    {
                        if (t.Exception == null)
                        {
                            Console.WriteLine(t.Result);
                        }
                        else
                        {
                            MessageBox.Show(t.Exception.GetBaseException().ToString());
                        }
                    }, TaskScheduler.FromCurrentSynchronizationContext());
            }
            else
            {
                Console.WriteLine("TryDequeue failed");
            }
        }
        task.Start();
    }

    ConcurrentQueue<T>是先进先出的线程安全的集合,使用非常简单,相关概念仍请查阅CSDN。TaskContinuationOptions.ExecuteSynchronously保证了任务的排队顺序。

    逻辑是先创建一个什么也不干的任务,然后遍历集合,为该任务顺序添加工作,并在工作完成后处理结果与异常。

    示例已经过测试。

  • 相关阅读:
    【ArchSummit干货分享】个推大数据金融风控算法实践
    Markdown 使用锚点
    部署ghost博客
    部署git server
    ubuntu 修改ssh远程主机名称,mac开机运行命令,静默方式启动virtual box虚拟机,静默执行run脚本
    meteor 实现 微信分享
    Android or iOS 运行 meteor App 屏幕一片空白 White screen的解决方法
    Ubuntu 修改用户密码与启动root账号
    meteor icons & splash配置
    meteor 安装 android sdk慢的改进方法
  • 原文地址:https://www.cnblogs.com/Jusfr/p/2638169.html
Copyright © 2011-2022 走看看