在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. CentOS系统配置 iptables防火墙

    阿里云CentOS系统配置iptables防火墙   虽说阿里云推出了云盾服务,但是自己再加一层防火墙总归是更安全些,下面是我在阿里云vps上配置防火墙的过程,目前只配置INPUT.OUTPUT和FO ...

  2. logstash+elasticsearch+kibana管理日志(安装)

    logstash1.先安装jdk2.wget https://download.elastic.co/logstash/logstash/logstash-2.4.0.tar.gz tar -xzvf ...

  3. 9.2.1 .net framework下的MVC 控件的封装(上)

    在写.net core下mvc控件的编写之前,我先说一下.net framework下我们MVC控件的做法. MVC下控件的写法,主要有如下三种,最后一种是泛型的写法,mvc提供的控件都是基本控件. ...

  4. 【IOS开发笔记03-视图相关】简单计算器的实现

    UIView 经过前几天的快速学习,我们初步了解的IOS开发的一些知识,中间因为拉的太急,忽略了很多基础知识点,这些知识点单独拿出来学习太过枯燥,我们在今后的项目中再逐步补齐,今天我们来学习APP视图 ...

  5. java web之个人通讯录系统

    前天下了第一场雪,专业课老师给我们布置了一个期末小作业,真的感觉到寒假就要来临了.这个学期没过多久就要结束了.总结这学期,感觉还是有不少收获的.完成了当初许下的诺言,现在也越来越喜欢软件这个行业了,虽 ...

  6. Dagger2 (三) 总结篇

    一.Dagger2注入原理 Dagger2以自动生成代码的形式,帮助我们构建依赖图,在使用依赖的时候方便清晰,这里说明一点,在我们使用Dagger2的时候,绝大多数错误都是编译器就会暴漏出来,这也就决 ...

  7. nodejs---修改文件名字

    D:\node\update_name目录有如下文件: 1:文件夹:icons 2:js文件:update-name.js js文件代码: // 引入fs文件处理模块var fs = require( ...

  8. Java 相关书籍

    Effective Java 中文第二版: Java并发编程实践: Java核心技术(原书第8版)卷I_基础知识: Java核心技术(原书第8版)卷II_高级特性: 深入理解Java虚拟机 JVM高级 ...

  9. MySQL解压版配置步骤

    mysql-5.7.14-winx64\bin配置到Path中 在解压路径下复制my-default.ini,修改名称为my.ini 在my.ini添加如下 [mysqld] basedir=C:\\ ...

  10. 安装Nginx服务

    Nginx最大特点: 静态小文件(1M),支持高并发,同时占用系统资源很少.3W并发,10个进程,内存150M. Nginx特点: 1.配置简单,灵活,轻量. 2.高并发(静态小文件),静态几万的并发 ...