美文网首页.NET多线程
.NET多线程(五)异步操作

.NET多线程(五)异步操作

作者: 万州大牛 | 来源:发表于2017-03-12 19:31 被阅读0次

5、异步操作

5.1 异步操作基础

异步操作发展历史,APM模式,EAP模式,TPL模式

.NET 1.0

System.Threading.Thread
适用耗时操作、特殊操作、低优先级操作,默认前台

System.Threading.ThreadPool
适合短时操作,线程池线程默认后台

# APM 异步操作模式

.NET 2.0

Thread 构造支持 ParameterizedThreadStart 传参数

匿名方法 delegate,闭包

ParameterizedThreadStart start = delegate(object obj) { };

同步上下文 SynchronizationContext
主要用在桌面UI应用 Send(同步) or Post(异步)

# EAP 异步操作模式

.NET 3.5

拉姆达表达式

泛型委托 Action 无返回结果,Func 最后必须结果

Action a1 = new Action(() => { });
Action<string> a2 = new Action<string>((s) => { });
Func<string> f1 = new Func<string>(() => { return ""; });
Func<int, string> f2 = new Func<int, string>((n) => { return n.ToString(); });

.NET 4.0

线程池线程最大数量,是根据电脑内存来计算的

优化线程池工作项排序
在 .net 4.0 以前,线程池的工作项,采用链表排队
现在CPU都是多核处理器,假设现在有很多工作项
出现的问题:
(1)链表结构会存在很多引用,对垃圾回收影响很大
(2)链表是按顺序操作,多核CPU真正的并发受到影响
在 .net 4.0 重新设计工作项排队结构
数组+链表
数组元素对应工作项引用
(1)引用减少了
(2)现在是操作数组元素

# TPL 异步操作模式

5.2 异步操作模式

(1)APM 模式 Asynchronous Programming Model

2个方法 Begin/End,1个 IAsyncResult

必须调用 End,即使不需要返回结果,因为 End 会把线程的异常抛出来
调用 End 加 try/catch
调用 Begin 之后,应当避免直接调用 End,因为 End 会等待结果,可能无限等待

APM 获取结果

(1)轮询是否完成

主要使用 System.Windows.Forms.Timer
轮询 IAsyncResult 的 IsCompleted,并调用 End 获取结果

(2)等待完成,IAsyncResult 的 AsyncWaitHandle 可以设置超时

直接调用 End,可能因为线程死锁等,无限等待
使用 AsyncWaitHandle 可以设置超时,但是超时了就不会调用 End
不调用 End 就意味着线程的,异常可能没捕获,资源可能泄露
所以 AsyncWaitHandle 并不完美

(3)完成时回调,AsyncCallback

这里有个问题,就是回调并不是在UI线程,如果要更新UI控件,那就不可以

static void Main(string[] args)
{
    HelloDelegate helloDelegate = new HelloDelegate(Hello);
    helloDelegate.BeginInvoke(Callback, helloDelegate);
    Console.ReadLine();
}
static void Callback(IAsyncResult ar)
{
    HelloDelegate helloDelegate = ar.AsyncState as HelloDelegate;
    try
    {
        string s = helloDelegate.EndInvoke(ar);
        Console.WriteLine(s);
    }
    catch (Exception) { }
}
static string Hello()
{
    return "hello";
}
public delegate string HelloDelegate();

APM 其他事

.NET 框架的一些类已经实现了 APM 模式
例如:使用 I/O thread 的 WebRequest,Stream,Socket,SqlCommand,MessageQueue 等

委托内在支持 APM 模式,使用(worker thread)

(2)EAP 模式 Event-Based Asynchronous Pattern

1个异步Async方法,1个Completed事件

static void Main(string[] args)
{
    WebClient webClient = new WebClient();
    webClient.DownloadDataCompleted += delegate(object sender, DownloadDataCompletedEventArgs e)
    {
        try
        {
            byte[] result = e.Result;
        }
        catch (Exception) { }
    };
    webClient.DownloadDataAsync(new Uri(""));
}

在获取 Result 的时候, try/catch
EAP 有个问题,如果发起多个异步请求,在完成事件里,需要区分结果来自哪个异步操作呢

(3)TPL 模式 Task Parallel Library

基于 System.Threading.Tasks.Task
实现标准的取消线程,报告线程进度操作

Task 本质代表未来的操作

Task task = new Task(() =>
{
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    throw new Exception("error");
});
task.Start();
task.ContinueWith((t) =>
{
    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
    Console.WriteLine(t.Exception.InnerException.Message);
}, TaskContinuationOptions.OnlyOnFaulted);
Console.ReadLine();

相关文章

  • .NET多线程(五)异步操作

    5、异步操作 5.1 异步操作基础 异步操作发展历史,APM模式,EAP模式,TPL模式 .NET 1.0 Sys...

  • 项目经验

    设计技巧:1、回调处理(调用方回调处理)2、批量操作(批量操作提高性能)3、mq + 异步化(消息队列+多线程异步...

  • WPF针对性学习的知识点

    1、跨线程操作(Dispatcher) 2、多线程(异步编程和async/await) 3、template(模板...

  • 基于Swoole和Redis实现的并发队列处理系统

    背景 由于PHP不支持多线程,但是作为一个完善的系统,有很多操作都是需要异步完成的。为了完成这些异步操作,我们做了...

  • 多线程

    多线程开发 - 异步 多线程 - 延迟 多线程 - 异步延迟 discardableResult 就是说返回值可以...

  • iOS多线程操作:NSThread

    在我们开发过程中我们经常会用到多线程开发,比如在异步线程中加载资源,执行好使操作等,在iOS开发中常见的多线程操作...

  • 2018-05-24-多线程学习

    java多线程并发的编程学习 1,概念的学习 同步异步:同步需要等待异步不需要,同步如对共享数据操作避免脏数据...

  • RocketMQ消息队列还没入门就想放弃

    题外话 什么情况下的异步操作需要使用消息队列而不是多线程? 消息队列和多线程两者并不冲突,多线程可以作为队列的生产...

  • 细说 async/await

    其他相关传送门 Promise异步操作详解[https://blog.csdn.net/x550392236/ar...

  • 为什么发送邮件要使用消息队列而不是多线程

    什么情况下的异步操作使用消息队列而不是多线程?消息队列和多线程两者并不冲突,多线程可以作为队列的生产者和消费者。使...

网友评论

    本文标题:.NET多线程(五)异步操作

    本文链接:https://www.haomeiwen.com/subject/tkjgbttx.html