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