winform和wpf里必知的多线程知识

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

1 ,开启一个新的任务

        var param = 123;

 //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为例

2, 回到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);
                 });
            });

3, 高级方法

使用 SynchronizationContext

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

4,更多高级用法

扫描二维码关注公众号,回复: 9219015 查看本文章
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() { }
    }
}

猜你喜欢

转载自www.cnblogs.com/gxrsprite/p/12321759.html