最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

.NET4.0版本中基于任務(wù)的異步模式(TAP)

 更新時(shí)間:2022年06月09日 09:58:54   作者:springsnow  
這篇文章介紹了.NET4.0版本中基于任務(wù)的異步模式(TAP),文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

一、引言

當(dāng)使用APM的時(shí)候,首先我們要先定義用來(lái)包裝回調(diào)方法的委托,這樣難免有點(diǎn)繁瑣, 然而使用EAP的時(shí)候,我們又需要實(shí)現(xiàn)Completed事件和Progress事件,上面兩種實(shí)現(xiàn)方式感覺(jué)都有點(diǎn)繁瑣。

同時(shí)微軟也意識(shí)到了這點(diǎn),所以在.NET 4.0中提出了一個(gè)新的異步模式——基于任務(wù)的異步模式TAP(Task-based Asynchronous Pattern )。

基于任務(wù)的異步模式 (TAP) 是基于 System.Threading.Tasks.Task 命名空間中的 System.Threading.Tasks.Task 和 System.Threading.Tasks類(lèi)型,這些類(lèi)型用于表示任意異步操作。是用于新開(kāi)發(fā)的建議的異步設(shè)計(jì)模式。

二、什么是TAP——基于任務(wù)的異步模式介紹

當(dāng)看到類(lèi)中存在TaskAsync為后綴的方法時(shí)就代表該類(lèi)實(shí)現(xiàn)了TAP并且基于任務(wù)的異步模式同樣也支持異步操作的取消和進(jìn)度的報(bào)告的功能。

在TAP實(shí)現(xiàn)中,我們只需要通過(guò)向異步方法傳入CancellationToken 參數(shù),因?yàn)樵诋惒椒椒▋?nèi)部會(huì)對(duì)這個(gè)參數(shù)的IsCancellationRequested屬性進(jìn)行監(jiān)控,當(dāng)異步方法收到一個(gè)取消請(qǐng)求時(shí),異步方法將會(huì)退出執(zhí)行。

在TAP中,我們可以通過(guò)IProgress接口來(lái)實(shí)現(xiàn)進(jìn)度報(bào)告的功能。

1、計(jì)算密集型任務(wù)

例如,請(qǐng)考慮使用呈現(xiàn)圖像的異步方法。

任務(wù)的主體可以輪詢(xún)?nèi)∠麡?biāo)記,如果在呈現(xiàn)過(guò)程中收到取消請(qǐng)求,代碼可提前退出。 此外,如果啟動(dòng)之前收到取消請(qǐng)求,你需要阻止操作:

internal Task RenderAsync(ImageData data, CancellationToken cancellationToken)
{
    return Task.Run(() =>
    {
        var bmp = new Bitmap(data.Width, data.Height);
        for(int y=0; y)
        {
            cancellationToken.ThrowIfCancellationRequested();
            for(int x=0; x)
            {
                // render pixel [x,y] into bmp
            }
        }
        return bmp;
    }, cancellationToken);
}

2、I/O 密集型任務(wù):

假設(shè)你想創(chuàng)建一個(gè)將在指定時(shí)間段后完成的任務(wù)。 例如,你可能想延遲用戶(hù)界面中的活動(dòng)。

System.Threading.Timer 類(lèi)已提供在指定時(shí)間段后以異步方式調(diào)用委托的能力,并且你可以通過(guò)使用 TaskCompletionSource 將 Task 前端放在計(jì)時(shí)器上,例如:

public static Task Delay(int millisecondsTimeout)
   {
       TaskCompletionSource tcs = null;
       Timer timer = null;

       timer = new Timer(delegate
       {
           timer.Dispose();
           tcs.TrySetResult(DateTimeOffset.UtcNow);
       }, null, Timeout.Infinite, Timeout.Infinite);

       tcs = new TaskCompletionSource(timer);
       timer.Change(millisecondsTimeout, Timeout.Infinite);
       return tcs.Task;
   }

從 .NET Framework 4.5 開(kāi)始,Task.Delay 方法正是為此而提供的,并且你可以在另一個(gè)異步方法內(nèi)使用它。例如,若要實(shí)現(xiàn)異步輪詢(xún)循環(huán):

public static async Task Poll(Uri url, CancellationToken cancellationToken,  IProgress<bool> progress)
{
    while(true)
    {
        await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
        bool success = false;
        try
        {
            await DownloadStringAsync(url);
            success = true;
        }
        catch { /* ignore errors */ }
        progress.Report(success);
    }
}

三、如何使用TAP——使用基于任務(wù)的異步模式來(lái)異步編程

下面就讓我們實(shí)現(xiàn)自己的異步方法(亮點(diǎn)為只需要一個(gè)方法就可以完成進(jìn)度報(bào)告和異步操作取消的功能)

// Download File CancellationToken 參數(shù)賦值獲得一個(gè)取消請(qǐng)求 progress參數(shù)負(fù)責(zé)進(jìn)度報(bào)告
private void DownLoadFile(string url, CancellationToken ct, IProgress<int> progress)
{
    HttpWebRequest request = null;
    HttpWebResponse response = null;
    Stream responseStream = null;
    int bufferSize = 2048;
    byte[] bufferBytes = new byte[bufferSize];
    try
    {
        request = (HttpWebRequest)WebRequest.Create(url);
        if (DownloadSize != 0)
        {
            request.AddRange(DownloadSize);
        }

        response = (HttpWebResponse)request.GetResponse();
        responseStream = response.GetResponseStream();
        int readSize = 0;
        while (true)
        {
            // 收到取消請(qǐng)求則退出異步操作
            if (ct.IsCancellationRequested == true)
            {
                MessageBox.Show(String.Format("下載暫停,下載的文件地址為:{0}\n 已經(jīng)下載的字節(jié)數(shù)為: {1}字節(jié)", downloadPath, DownloadSize));

                response.Close();
                filestream.Close();
                sc.Post((state) =>
                {
                    this.btnStart.Enabled = true;
                    this.btnPause.Enabled = false;
                }, null);

                // 退出異步操作
                break;
            }

            readSize = responseStream.Read(bufferBytes, 0, bufferBytes.Length);
            if (readSize > 0)
            {
                DownloadSize += readSize;
                int percentComplete = (int)((float)DownloadSize / (float)totalSize * 100);
                filestream.Write(bufferBytes, 0, readSize);

                // 報(bào)告進(jìn)度
                progress.Report(percentComplete);
            }
            else
            {
                MessageBox.Show(String.Format("下載已完成,下載的文件地址為:{0},文件的總字節(jié)數(shù)為: {1}字節(jié)", downloadPath, totalSize));

                sc.Post((state) =>
                {
                    this.btnStart.Enabled = false;
                    this.btnPause.Enabled = false;
                }, null);

                response.Close();
                filestream.Close();
                break;
            }
        }
    }
    catch (AggregateException ex)
    {
        // 因?yàn)檎{(diào)用Cancel方法會(huì)拋出OperationCanceledException異常 將任何OperationCanceledException對(duì)象都視為以處理
        ex.Handle(e => e is OperationCanceledException);
    }
}

這樣只需要上面的一個(gè)方法,我們就可以完成上一專(zhuān)題中文件下載的程序,我們只需要在下載按鈕的事件處理程序調(diào)用該方法和在暫停按鈕的事件處理程序調(diào)用CancellationTokenSource.Cancel方法即可,具體代碼為:

#region 字段

private int DownloadSize = 0;
private string downloadPath = null;
private long totalSize = 0;
private FileStream filestream;

private CancellationTokenSource cts = null;
private Task task = null;

private SynchronizationContext sc;

#endregion 字段

#region 構(gòu)造函數(shù)

public FileDownLoadForm()
{
    InitializeComponent();
    string url = "http://download.microsoft.com/download/7/0/3/703455ee-a747-4cc8-bd3e-98a615c3aedb/dotNetFx35setup.exe";
    txbUrl.Text = url;
    this.btnPause.Enabled = false;

    // Get Total Size of the download file
    GetTotalSize();
    downloadPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + Path.GetFileName(this.txbUrl.Text.Trim());
    if (File.Exists(downloadPath))
    {
        FileInfo fileInfo = new FileInfo(downloadPath);
        DownloadSize = (int)fileInfo.Length;
        if (DownloadSize == totalSize)
        {
            string message = "There is already a file with the same name, do you want to delete it? If not, please change the local path. ";
            var result = MessageBox.Show(message, "File name conflict: " + downloadPath, MessageBoxButtons.OKCancel);

            if (result == System.Windows.Forms.DialogResult.OK)
            {
                File.Delete(downloadPath);
            }
            else
            {
                progressBar1.Value = (int)((float)DownloadSize / (float)totalSize * 100);
                this.btnStart.Enabled = false;
                this.btnPause.Enabled = false;
            }
        }
    }
}

#endregion 構(gòu)造函數(shù)

#region 方法

// Start DownLoad File
private void btnStart_Click(object sender, EventArgs e)
{
    filestream = new FileStream(downloadPath, FileMode.OpenOrCreate);
    this.btnStart.Enabled = false;
    this.btnPause.Enabled = true;

    filestream.Seek(DownloadSize, SeekOrigin.Begin);

    // 捕捉調(diào)用線(xiàn)程的同步上下文派生對(duì)象
    sc = SynchronizationContext.Current;

    cts = new CancellationTokenSource();
    // 使用指定的操作初始化新的 Task。
    task = new Task(() => Actionmethod(cts.Token), cts.Token);

    // 啟動(dòng) Task,并將它安排到當(dāng)前的 TaskScheduler 中執(zhí)行。
    task.Start();

    //await DownLoadFileAsync(txbUrl.Text.Trim(), cts.Token,new Progress(p => progressBar1.Value = p));
}

// 任務(wù)中執(zhí)行的方法
private void Actionmethod(CancellationToken ct)
{
    // 使用同步上文文的Post方法把更新UI的方法讓主線(xiàn)程執(zhí)行
    DownLoadFile(txbUrl.Text.Trim(), ct, new Progress<int>(p =>
        {
            sc.Post(new SendOrPostCallback((result) => progressBar1.Value = (int)result), p);
        }));
}

// Pause Download
private void btnPause_Click(object sender, EventArgs e)
{
    // 發(fā)出一個(gè)取消請(qǐng)求
    cts.Cancel();
}

// Get Total Size of File
private void GetTotalSize()
{
    HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(txbUrl.Text.Trim());
    HttpWebResponse response = (HttpWebResponse)myHttpWebRequest.GetResponse();
    totalSize = response.ContentLength;
    response.Close();
}

四、與其他異步模式和類(lèi)型互操作

1、從 APM 到 TAP

可以使用 TaskFactory.FromAsync 方法來(lái)實(shí)現(xiàn)此操作的 TAP 包裝,如下所示:

public static Task<int> ReadAsync(this Stream stream,  byte[] buffer, int offset,  int count)
{
    if (stream == null) 
       throw new ArgumentNullException("stream");
    
    return Task<int>.Factory.FromAsync(stream.BeginRead,  stream.EndRead, buffer,   offset, count, null);
}

此實(shí)現(xiàn)類(lèi)似于以下內(nèi)容: 

 public static Task<int> ReadAsync(this Stream stream,  byte [] buffer, int offset,   int count)
 {
    if (stream == null) 
        throw new ArgumentNullException("stream");

    var tcs = new TaskCompletionSource<int>();

    stream.BeginRead(buffer, offset, count, iar =>
                     {
                        try { 
                           tcs.TrySetResult(stream.EndRead(iar)); 
                        }
                        catch(OperationCanceledException) { 
                           tcs.TrySetCanceled(); 
                        }
                        catch(Exception exc) { 
                           tcs.TrySetException(exc); 
                        }
                     }, null);
    return tcs.Task;
}

2、從EAP到 TAP

public static Task<string> DownloadStringAsync(Uri url)
 {
     var tcs = new TaskCompletionSource<string>();

     var wc = new WebClient();

     wc.DownloadStringCompleted += (s,e) =>
         {
             if (e.Error != null) 
                tcs.TrySetException(e.Error);
             else if (e.Cancelled) 
                tcs.TrySetCanceled();
             else 
                tcs.TrySetResult(e.Result);
         };
     wc.DownloadStringAsync(url);
     return tcs.Task;
}

到此這篇關(guān)于.NET4.0異步模式(TAP)的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • ASP.NET中MultiView和View選項(xiàng)卡控件的使用方法

    ASP.NET中MultiView和View選項(xiàng)卡控件的使用方法

    ASP.NET中的MultiView和View控件可以作為承載其他控件的容器,一般我們都很少使用,本文主要介紹使用MultiView和View實(shí)現(xiàn)選項(xiàng)卡效果。
    2016-04-04
  • ASP.NET中Cookie的使用方法

    ASP.NET中Cookie的使用方法

    Cookie是一段文本信息,在客戶(hù)端存儲(chǔ) Cookie 是 ASP.NET 的會(huì)話(huà)狀態(tài)將請(qǐng)求與會(huì)話(huà)關(guān)聯(lián)的方法之一。瀏覽器對(duì) Cookie 的大小有限制,因此,只有不超過(guò) 4096 字節(jié)才能保證被接受。
    2016-04-04
  • ASP.NET中BulletedList列表控件使用及詳解

    ASP.NET中BulletedList列表控件使用及詳解

    本文主要介紹了ASP.NET中BulletedList列表控件的詳細(xì)使用方法,講解各屬性的含義以及三種顯示模式,希望能幫到大家。
    2016-04-04
  • SQL Server 2005 RTM 安裝錯(cuò)誤 :The SQL Server System Configuration Checker cannot be executed due to

    SQL Server 2005 RTM 安裝錯(cuò)誤 :The SQL Server System Configuratio

    SQL Server 2005 RTM 安裝錯(cuò)誤 :The SQL Server System Configuration Checker cannot be executed due to...
    2007-02-02
  • ASP.NET中 PlaceHolder 控件的使用方法

    ASP.NET中 PlaceHolder 控件的使用方法

    有時(shí)候項(xiàng)目中需要在頁(yè)面上動(dòng)態(tài)生成一些控件,所以PlaceHolder容器是個(gè)不錯(cuò)的選擇。微軟在asp.net 2.0 中給出的PlaceHolder解決方案,更加符合后臺(tái)和表現(xiàn)分離的原則。
    2016-04-04
  • .NET設(shè)計(jì)模式之UML類(lèi)圖介紹

    .NET設(shè)計(jì)模式之UML類(lèi)圖介紹

    這篇文章介紹了.NET設(shè)計(jì)模式之UML類(lèi)圖,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • C#編碼好習(xí)慣小結(jié)

    C#編碼好習(xí)慣小結(jié)

    c#編寫(xiě)比較好的習(xí)慣
    2008-04-04
  • ASP.NET?CORE讀取json格式配置文件

    ASP.NET?CORE讀取json格式配置文件

    這篇文章介紹了ASP.NET?CORE讀取json格式配置文件的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • 檢測(cè)含有中文字符串的實(shí)際長(zhǎng)度

    檢測(cè)含有中文字符串的實(shí)際長(zhǎng)度

    檢測(cè)含有中文字符串的實(shí)際長(zhǎng)度...
    2006-08-08
  • .NET?6中System.Text.Json的七個(gè)特性

    .NET?6中System.Text.Json的七個(gè)特性

    這篇文章介紹了.NET?6中System.Text.Json的七個(gè)特性,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01

最新評(píng)論

遵化市| 报价| 台江县| 米泉市| 青海省| 长垣县| 达日县| 江西省| 民县| 闵行区| 济源市| 庆元县| 武安市| 崇义县| 民和| 宜宾县| 淅川县| 额尔古纳市| 永年县| 西充县| 罗定市| 怀远县| 淳安县| 车致| 怀化市| 安平县| 康马县| 沾益县| 泾源县| 霸州市| 九龙县| 阳西县| 贵州省| 简阳市| 龙南县| 昌吉市| 潼南县| 孝昌县| 龙口市| 赫章县| 乌兰浩特市|