在非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();
}
}
在非UI线程中自制Dispatcher的更多相关文章
- WPF非UI线程中调用App.Current.MainWindow.Dispatcher提示其他线程拥有此对象,无权使用。
大家都知道在WPF中对非UI线程中要处理对UI有关的对象进行操作,一般需要使用委托的方式,代码基本就是下面的写法 App.Current.MainWindow.Dispatcher.Invoke(ne ...
- 一个解决在非UI线程中访问UI 异常的小方法
写 WPF 的童鞋可能都会碰到 在非UI线程中访问 UI 异常的问题.这是为了防止数据不一致做的安全限制. 子线程中更新UI还要交给主线程更新,引用满天飞,实在是麻烦. 接下来,我们推出一个可以称之为 ...
- Android 高级UI设计笔记17:Android在非UI线程中显示Toast
1. 子线程的Toast怎么显示不出来? 因为Toast在创建的时候会依赖于一个Handler,并且一个Handler是需要有一个Looper才能够创建,而普通的线程是不会自动去创建一个Looper对 ...
- Android开之在非UI线程中更新UI
当在非UI线程中更新UI(程序界面)时会出现例如以下图所看到的的异常: 那怎样才干在非UI线程中更细UI呢? 方法有非常多种.在这里主要介绍三种: 第一种:调用主线程mHandler的post(Run ...
- 为什么在非UI线程中操作UI的改变失不安全的
因为你如果允许在非UI线程更新操作UI的东西,那我再另一个非UI线程也可以更新这个Ui的东西 这样就会有冲突,比如你的线程刚好跑到修改UI这里,我的另一个UI也有可能跑到这里,所以这样导致线程不安全. ...
- Android在非UI线程中更新UI的方法
1.使用Thread+Handler实现非UI线程更新UI界面 在UI Thread中创建Handler.用sendMessage(message)或者obtainMessage(result, ob ...
- Android中高效的显示图片之二——在非UI线程中处理图片
在“加载大图”文章中提到的BitmapFactory.decode*方法,如果源数据是在磁盘.网络或其它任何不是在内存中的位置,那么它都不应该在UI线程中执行.因为它的加载时间不可预测且依赖于一系列因 ...
- UWP 在非UI线程中更新UI
大家都知道,不可以在 其他线程访问 UI 线程,访问 UI 线程包括给 依赖属性设置值.读取依赖属性.调用方法(如果方法里面修改了依赖属性)等.一旦访问UI线程,那么就会报错,为了解决这个问题,需要使 ...
- 在非UI线程中更改UI(Delphi使用隐藏窗口来处理,QT使用信号槽)
在Delphi里我记得是使用TThread.Synchronize(TThreadMethod),原理是利用了一个隐藏窗口来处理. 在QT Debug模式一下,碰到了同样的问题,显示错误: canno ...
随机推荐
- 《连载 | 物联网框架ServerSuperIO教程》- 6.并发通讯模式开发及注意事项
1.C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 <连载 | 物联网框架ServerSuperIO教程>1.4种通讯模式机制. <连载 | 物联网框架Serve ...
- [转载]IIS7报500.23错误的解决方法
原文出处: 原文作者:pizibaidu 原文链接:http://pizibaidu.blog.51cto.com/1361909/1794446 背景:今天公司终端上有一个功能打开异常,报500错误 ...
- js通过循环多张图片实现动画效果
以小鱼摇尾巴和眨眼睛为例 动画思路: 1.将图片资源放在数组里面 2.通过计时器来设定间隔时间 3.通过计数器来取相应的图片 第一步:基本框架,鱼身体 <body> <canvas ...
- RMI(远程接口调用)
1. RMI的原理: RMI系统结构,在客户端和服务器端都有几层结构. 方法调用从客户对象经占位程序(Stub).远程引用层(Remote Reference Layer)和传输层(Transport ...
- Markdown学习
1. Markdown介绍 Markdown是一种轻量级的标记语言,它语法简单并且易读易用.Mardown文件通常以.md后缀结尾. 2. Markdown优点 纯文本格式,兼容性极强,可以用任意文本 ...
- 有主线程发送message给子线程
通常我们在处理耗时任务时候都会通过新建线程来处理,当任务处理完后通过Handler将结果发送回主线程.比如下面示例: package com.example.testlistener; import ...
- couchDB视图
视图是设计文档的一部分. 视图函数 map函数 Map方法的参数只有一个,就是当前的文档对象.Map方法的实现需要根据文档对象的内容,确定是否要输出结果. 如果需要输出的话,可以通过emit来完成. ...
- FE
<link rel="stylesheet" type="text/css" media="screen" href="li ...
- 关于 IIS 中 Excel 访问的问题
关于 IIS 上 Excel 文件的访问, 一路上困难重重, 最后按以下步骤进行设置, 可在 IIS 中正常使用! 1. 引用及代码: 1). 项目中添加 Excel 程序集引用(注意: 从系统 CO ...
- 国际化(Internationalization)
1:什么是国际化? 国际化(internationalization)是设计和制造容易适应不同区域要求的产品的一种方式.它要求从产品中抽离所有的与语言,国家/地区和文化相关的元素.换言之,应用程序的功 ...