在非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(); } }