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

在非UI线程中自制Dispatcher的更多相关文章

  1. WPF非UI线程中调用App.Current.MainWindow.Dispatcher提示其他线程拥有此对象,无权使用。

    大家都知道在WPF中对非UI线程中要处理对UI有关的对象进行操作,一般需要使用委托的方式,代码基本就是下面的写法 App.Current.MainWindow.Dispatcher.Invoke(ne ...

  2. 一个解决在非UI线程中访问UI 异常的小方法

    写 WPF 的童鞋可能都会碰到 在非UI线程中访问 UI 异常的问题.这是为了防止数据不一致做的安全限制. 子线程中更新UI还要交给主线程更新,引用满天飞,实在是麻烦. 接下来,我们推出一个可以称之为 ...

  3. Android 高级UI设计笔记17:Android在非UI线程中显示Toast

    1. 子线程的Toast怎么显示不出来? 因为Toast在创建的时候会依赖于一个Handler,并且一个Handler是需要有一个Looper才能够创建,而普通的线程是不会自动去创建一个Looper对 ...

  4. Android开之在非UI线程中更新UI

    当在非UI线程中更新UI(程序界面)时会出现例如以下图所看到的的异常: 那怎样才干在非UI线程中更细UI呢? 方法有非常多种.在这里主要介绍三种: 第一种:调用主线程mHandler的post(Run ...

  5. 为什么在非UI线程中操作UI的改变失不安全的

    因为你如果允许在非UI线程更新操作UI的东西,那我再另一个非UI线程也可以更新这个Ui的东西 这样就会有冲突,比如你的线程刚好跑到修改UI这里,我的另一个UI也有可能跑到这里,所以这样导致线程不安全. ...

  6. Android在非UI线程中更新UI的方法

    1.使用Thread+Handler实现非UI线程更新UI界面 在UI Thread中创建Handler.用sendMessage(message)或者obtainMessage(result, ob ...

  7. Android中高效的显示图片之二——在非UI线程中处理图片

    在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...

  8. UWP 在非UI线程中更新UI

    大家都知道,不可以在 其他线程访问 UI 线程,访问 UI 线程包括给 依赖属性设置值.读取依赖属性.调用方法(如果方法里面修改了依赖属性)等.一旦访问UI线程,那么就会报错,为了解决这个问题,需要使 ...

  9. 在非UI线程中更改UI(Delphi使用隐藏窗口来处理,QT使用信号槽)

    在Delphi里我记得是使用TThread.Synchronize(TThreadMethod),原理是利用了一个隐藏窗口来处理. 在QT Debug模式一下,碰到了同样的问题,显示错误: canno ...

随机推荐

  1. java 开发模式

    Java-开发模式 Java Web开发方案有多种,这里列举一些经典的开发模式进行横向比较JSP+JAVABEAN开发模式:    特点:该模式将业务逻辑与页面表现进行分离,在一定程度上增加了程序的可 ...

  2. Oracle SQL性能优化

    (1)      选择最有效率的表名顺序(只在基于规则的优化器中有效):ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table) ...

  3. spider RPC性能测试报告

    测试环境部署结构 测试用例 类 别 说明 请求报文 194字节({"systemId":"PL","appVersion":"qq ...

  4. 升级Centos的python为2.7(centos python 升级)

    1.首先下载python的2.7.8版本的tar包.为什么没有选择最新版本的3.4呢?因为3版本的兼容性不好.很多一些成熟的项目都是基于2.7开发的. https://www.python.org/d ...

  5. jquery css3问卷答题卡翻页动画效果

    这个选项调查的特效以选项卡的形式,每答完一道题目自动切换到下一条,颇具特色.使用jQuery和CSS3,适合HTML5浏览器. 效果展示 http://hovertree.com/texiao/jqu ...

  6. jquery手风琴

    --js $(document).ready(function(){ //Set default open/close settings$('.acc_container').hide(); //Hi ...

  7. SharePoint 2013 开发教程

    做了SharePoint有三年了,大家经常会问到,你的SharePoint是怎么学的,想想自己的水平,也不过是初级开发罢了.因为,SharePoint开发需要接触的东西太多了,Windows操作系统. ...

  8. .a静态库构架合成

    一.如果类库生成的构架和对应设备的构架不一致,会链接报错 如果项目中使用类库后,遇到形似Undefined symbols for architecture x86_64(x86_64架构下有未定义的 ...

  9. installshield使用教程

    从Visual Studio 2012开始,微软就把自家原来的安装与部署工具彻底废掉了,转而让大家去安装使用第三方的打包工具“InstallShield Limited Edition for Vis ...

  10. Javascript——arguments的shift问题谈方法“借用”

    今天本来运行了打算这样的方法 arguments.shift() (shift方法是删除数组的第一个元素,例如var arr=[1,2,3,4,5]执行var a=arr.shift();之后,a的值 ...