在非UI线程中自制Dispatcher

在C#中,Task.Run当然是一个很好的启动新并行任务的机制,但是因为使用这个方法时,每次新的任务都会在一个新的线程中(其实就是线程池中的线程)运行

这样会造成某些情形下现场调度的相对困难,即使我隔离出一个与UI无关的对象,然后用UI线程的Dispatcher实现对UI线程的交互,但是用Task启动的多个任务线程却难以管理,而且.net Core UWP已经不再提供具体线程调度的管理了

最终我写了个这个玩意

 

    class NoUIDispatcher:IDisposable
    {
#if DEBUG
        ~NoUIDispatcher()
        {
            System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " bedeleted");
        }
#endif
        public async void Start()
        {
            await Task.Run(() =>
            {
                try
                {
                    normaltasklist = new List<Tuple<DispatchedHandler, OperationDeferral>>();
                    while (isdispose == false)
                    {
                        lock (normaltasklist)
                        {
                            if (normaltasklist.Count == 0)
                            {
                                od.Start();
                            }
                            else
                            {
                                normaltasklist[0].Item1.Invoke();
                                normaltasklist[0].Item2?.Complete();
                                normaltasklist.RemoveAt(0);
                            }
                        }
                        od.WaitOne();
                    }
                    normaltasklist = null;
                    System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " dispose");
                }
                catch
                {
                    System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " error");
                }
            });
        }
        OperationDeferral od = new OperationDeferral();
        List<Tuple<DispatchedHandler, OperationDeferral>> normaltasklist = null;

        public async Task RunAsync(DispatchedHandler agileCallback)
        {
            await Task.Run(() =>
            {
                try
                {
                    var pk = new OperationDeferral();
                    pk.Start();
                    /*if (normaltasklist == null)
                    {
                        System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " isdisposed");
                        return;
                    }*/
                    lock (normaltasklist)
                    {
                        normaltasklist.Add(new Tuple<DispatchedHandler, OperationDeferral>(agileCallback, pk));
                    }
                    od.CompleteWithoutDispose();
                    pk.WaitOne();
                }
#if DEBUG
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " " + e.ToString());
                }
#else
                catch { }
#endif
            });
        }
        public void Run(DispatchedHandler agileCallback)
        {
            Task.Run(() =>
            {
                try
                {
                    /*if (normaltasklist == null)
                    {
                        System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " isdisposed");
                        return;
                    }*/
                    lock (normaltasklist)
                    {
                        normaltasklist.Add(new Tuple<DispatchedHandler, OperationDeferral>(agileCallback, null));
                    }
                    od.CompleteWithoutDispose();
                }
#if DEBUG
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(nameof(NoUIDispatcher) + " " + e.ToString());
                }
#else
                catch { }
#endif
            }).IgnorCompletion();
        }
        bool isdispose = false;
        public void Dispose()
        {
            isdispose = true;
            od.Complete();
        }
    }

    public class OperationDeferral
    {
        System.Threading.AutoResetEvent are = new System.Threading.AutoResetEvent(false);
        public void Complete()
        {
            CompleteWithoutDispose();
            are.Dispose();
        }
        public void CompleteWithoutDispose()
        {
            are.Set();
        }
        public void Start()
        {
            are.Reset();
        }
        public Task WaitOneAsync()
        {
            return Task.Run(() =>
            {
                try
                {
                    are.WaitOne();
                }
                catch { }
            });
        }
        public void WaitOne()
        {
            are.WaitOne();
        }
    }

 

posted @ 2017-01-07 15:41  yinyue200  阅读(186)  评论(6编辑  收藏  举报
知识共享许可协议
本博客原创内容默认采用知识共享署名 4.0 国际许可协议进行许可。