背景: 很多小伙伴经常在群里问线程的问题,平时我经常转一些视频教程这些人不看,我就自己写个总结吧

不过还是要注意的是,切换本来就不能太频繁,要一口气改。

UI线程切换的核心思路是

1,这行代码会直接修改UI的,必须放在UI线程,掌握这条你可以自己把winform的线程检查关掉,将Control类的静态属性CheckForIllegalCrossThreadCalls设为false,必须心里有数才能做此操作

2,wpf也是如此,但是无法关闭线程检查,但是wpf的viewmodel就不需要UI线程,更新更方便,因为是内部通知的。

一,开启一个新的任务

        var param = ;

 //net4.5以后
Task.Run(() =>
{
DoSomthing(param);
}); Task.Run(async () =>
{
await DoSomthingAsync(param);
}); //net 4.0 Task.Factory.StartNew(delegate ()
{
DoSomthing(param);
}); //3.5
Thread t = new Thread((ThreadStart)delegate ()
{
DoSomthing(param);
});
t.Start();
//net 3.5 加线程池
ThreadPool.QueueUserWorkItem((WaitCallback)delegate (Object obj)
{
DoSomthing(param);
});

后面都用Task为例

二, 回到UI线程

//winform
Task.Run(() =>
{
//类似sendMessage 等待发送结束
this.Invoke((Action)delegate ()
{
DoSomthing(param);
});
//类似postmessage 发了就跑
this.BeginInvoke((Action)delegate ()
{
DoSomthing(param);
});
}); //wpf
Task.Run(async () =>
{
this.Dispatcher.Invoke(delegate ()
{
DoSomthing(param);
}); //使用异步等待任务结束
await this.Dispatcher.BeginInvoke((Action)delegate ()
{
DoSomthing(param);
});
//使用抛弃返回值的方式,直接过 不等待
_ = this.Dispatcher.BeginInvoke((Action)delegate ()
{
DoSomthing(param);
});
});
await Task.Run(async () =>
{
DoSomething();
}
//回到调用线程

  

三, 高级方法

1 使用 SynchronizationContext

            //在UI线程时记录下上下文
var syncContext = SynchronizationContext.Current;
Task.Run(() =>
{
//使用UI线程
syncContext.Post(o =>
{
DoSomthing(param);
}, null);
});

2  await一个SynchronizationContext

            //在UI线程时记录下上下文
var syncContext = SynchronizationContext.Current;
Task.Run(() =>
{
//回到UI线程
await syncContext;
DoSomthing(param);//在UI线程中
});

那么如何await一个SynchronizationContext呢?

//写个Awaiter类
public sealed class SynchronizationContextAwaiter : INotifyCompletion
{
private readonly SynchronizationContext _context;
public SynchronizationContextAwaiter(SynchronizationContext context) =>
_context = context ?? throw new ArgumentNullException("context"); public bool IsCompleted => SynchronizationContext.Current == _context;
public void OnCompleted(Action action) => _context.Post(x => action(), null);
public void GetResult() { }
} //接下去使用awaiter类,写个扩展方法
public static SynchronizationContextAwaiter GetAwaiter(this SynchronizationContext context)
{
return new SynchronizationContextAwaiter(context);
}

四,将三的内容整合到一个类中

需要在UI线程初始化:

UIThreadContext.Init();
using Ruifei.Common.UIThread;
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading; public static class UIThreadContext
{
public static SynchronizationContext Context;
public static Thread UIThread => uiThread;
static Thread uiThread = null;
public static void SendUIThread(Action action)
{
if (Context != null)
Context.Send(x => action(), null);
else
action();
} public static void SendUIThreadIfRequired(Action action)
{
Thread crt = Thread.CurrentThread;
if (uiThread != crt)
SendUIThread(action);
else
action();
} public static void PostUIThread(Action action)
{
if (Context != null)
Context.Post(x => action(), null);
else
action();
} public static void PostUIThread(Func<Task> action)
{
if (Context != null)
Context.Post(x => action(), null);
else
action();
} public static void PostUIThreadIfRequired(Action action)
{
if (IsInUIThread())
action();
else
PostUIThread(action);
} public static void PostUIThreadIfRequired(Func<Task> action)
{
if (IsInUIThread())
action();
else
PostUIThread(action);
} public static bool IsInUIThread()
{
return uiThread == Thread.CurrentThread;
} static Dispatcher dispatcher = (Application.Current != null && Application.Current.Dispatcher != null) ? Application.Current.Dispatcher : Dispatcher.CurrentDispatcher;
public async static void InvokeOnUIThread(Func<Task> action)
{
if (dispatcher == null || dispatcher.CheckAccess())
await action();
else
await dispatcher.BeginInvoke(action);
} public static void InvokeOnUIThread(Action action)
{
if (dispatcher == null || dispatcher.CheckAccess())
action();
else
dispatcher.BeginInvoke(action);
} public static void Init()
{
Context = SynchronizationContext.Current;
uiThread = Thread.CurrentThread;
} public static SynchronizationContextAwaiter GetAwaiter(this SynchronizationContext context)
{
return new SynchronizationContextAwaiter(context);
} /// <summary>
/// 切换到UI线程
/// </summary>
/// <returns></returns>
public static SynchronizationContext SwitchToUIThread()
{
return UIThreadContext.Context;
} /// <summary>
/// WithoutContext
/// </summary>
/// <returns></returns>
public static WaitForSwitchToNewTask SwitchToNewTask()
{
return new WaitForSwitchToNewTask(false);
}
} namespace Ruifei.Common.UIThread
{
public class WaitForSwitchToNewTask
{
bool withContext = false;
public WaitForSwitchToNewTask(bool _with)
{
withContext = _with;
}
public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter()
{
return Task.Run(() => { }).ConfigureAwait(withContext).GetAwaiter();
}
} public sealed class SynchronizationContextAwaiter : INotifyCompletion
{
private readonly SynchronizationContext _context;
public SynchronizationContextAwaiter(SynchronizationContext context) =>
_context = context ?? throw new ArgumentNullException("context"); public bool IsCompleted => SynchronizationContext.Current == _context;
public void OnCompleted(Action action)
{
if (_context == null)
{
action();
}
else
{
_context.Send(x => action(), null);
}
} public void GetResult() { }
}
}

winform和wpf里必知的多线程知识的更多相关文章

  1. python网络爬虫,知识储备,简单爬虫的必知必会,【核心】

    知识储备,简单爬虫的必知必会,[核心] 一.实验说明 1. 环境登录 无需密码自动登录,系统用户名shiyanlou 2. 环境介绍 本实验环境采用带桌面的Ubuntu Linux环境,实验中会用到桌 ...

  2. input屏蔽历史记录 ;function($,undefined) 前面的分号是什么用处 JSON 和 JSONP 两兄弟 document.body.scrollTop与document.documentElement.scrollTop兼容 URL中的# 网站性能优化 前端必知的ajax 简单理解同步与异步 那些年,我们被耍过的bug——has

    input屏蔽历史记录   设置input的扩展属性autocomplete 为off即可 ;function($,undefined) 前面的分号是什么用处   ;(function($){$.ex ...

  3. 15分钟带你了解前端工程师必知的javascript设计模式(附详细思维导图和源码)

    15分钟带你了解前端工程师必知的javascript设计模式(附详细思维导图和源码) 前言 设计模式是一个程序员进阶高级的必备技巧,也是评判一个工程师工作经验和能力的试金石.设计模式是程序员多年工作经 ...

  4. 必知必会之 Java

    必知必会之 Java 目录 不定期更新中-- 基础知识 数据计量单位 面向对象三大特性 基础数据类型 注释格式 访问修饰符 运算符 算数运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 三目表达式 ...

  5. Java面试必知必会:基础

    面试考察的知识点多而杂,要完全掌握需要花费大量的时间和精力.但是面试中经常被问到的知识点却没有多少,你完全可以用 20% 的时间去掌握 80% 常问的知识点. 一.基础 包括: 杂七杂八 面向对象 数 ...

  6. Visual Studio (VS IDE) 你必须知道的功能和技巧 - 【.Net必知系列】

    前言 本文主要阐述一些Visual Studio开发下需要知道的少部分且比较实用的功能,也是很多人忽略的部分.一些不常用而且冷门的功能不在本文范围,当然本文的尾巴[.Net必知系列]纯属意淫,如有雷同 ...

  7. .NET程序员项目开发必知必会—Dev环境中的集成测试用例执行时上下文环境检查(实战)

    Microsoft.NET 解决方案,项目开发必知必会. 从这篇文章开始我将分享一系列我认为在实际工作中很有必要的一些.NET项目开发的核心技术点,所以我称为必知必会.尽管这一系列是使用.NET/C# ...

  8. c++程序员必知的几个库

    c++程序员必知的几个库 1.C++各大有名库的介绍——C++标准库 2.C++各大有名库的介绍——准标准库Boost 3.C++各大有名库的介绍——GUI 4.C++各大有名库的介绍——网络通信 5 ...

  9. 高效能人士必知铁律--note

    偶然看到了<高效能人士 必知铁律>这本书,我比较少看成功学,但是这本书把很多著名的成功学书籍整理出来,有时会让你耳目一新,有些观点尽管是常识,但是却加深了你对它们的理解,比如: 只要在积极 ...

随机推荐

  1. Win下PHP5.6版本安装redis扩展

    首先说一下自己的环境啥的,我用的是phpstudy,其实没啥大用,就是看你的php版本啥的 1.运行phpinfo(),查看php的信息,php的位数和扩展信息,和要下载的扩展文件信息有关, 2.下载 ...

  2. tp5 自定义公共函数,前台模板调用

    最近用tp5做一个cms,在添加模型的时候,选择类型,这类型太多了,如果一个个的去判断显示,能累死人了,干脆写个公共方法, 首先写公共方法用到Common.php,目录project/applicat ...

  3. family_to_level函数

    #include <netinet/in.h> #include <sys/socket.h> int family_to_level(int family) { switch ...

  4. SpringCloud全家桶学习之一阶段总结(一)

    一.概述 前几篇小博客记录了我学习SpringCloud组件的过程,并与工作中所用的Dubbo框架做了一点比较,基本组件:Eureka.Ribbon.Hystrix.Feign.Zuul.Config ...

  5. ios 用touchend事件 pc用click touchend击穿

    var clickEvent = (function() { if ('ontouchend' in document.documentElement === true) return 'touche ...

  6. 「ZJOI2008」树的统计

    树剖模板题啊! 这道题的话,最通(jian)俗(dan)易(cu)懂(bao)的解法应该就是树剖了. 加上线段树维护树上路径的最大权值(\(Max\))和路径和(\(sum\)). 至于\(LCT\) ...

  7. Linux - 常用GUI软件

    1. gdebi -- 可以代替Ubuntu software安装软件 2. System monitor -- 监控流量 3. uget -- 下载软件 4. Okular -- pdf reade ...

  8. 15 FFT及其框图实现

    FFT及其框图实现 \(FFT\)的全称为快速傅里叶变换,但是\(FFT\)并不是一种变换,而是实现\(DFT\)的一种快速算法.当\(N\)比较大时,使用\(FFT\)可大大减少进行\(DFT\)变 ...

  9. 给Linux安装中文的man手册

    查找 yum list |grep man.*zh 安装 sudo yum install man-pages-zh-CN.noarch 配置 alias cman='man -M /usr//sha ...

  10. docker部署-windows环境

    docker部署-windows环境 1.      docker windows 1.1.    安装 win7或者win8需要利用docker toolbox来安装,其是一个docker工具集,w ...