如何使用Task.FromResult?


Task.FromResult

字數:889字

預計閱讀時間:3分鍾

1.解釋

官方定義:創建一個結果的、成功完成的Task<TResult>

public static System.Threading.Tasks.Task<TResult> FromResult<TResult> (TResult result);

可以看出,Task.FromResult( )方法接受一個TResult然后返回一個Task<TResult>

2.例子

使用 Task.FromResult方法檢索緩存中保存的異步下載操作的結果。

Ex:

​ 以下示例從Web下載字符串。它定義了DownloadStringAsync方法。此方法異步從Web下載字符串。此示例還使用ConcurrentDictionary <TKey,TValue>對象來緩存先前操作的結果。如果輸入地址保存在此緩存中,則DownloadStringAsync使用FromResult方法生成一個Task <TResult>對象,該對象保存該地址的內容。否則,DownloadStringAsyncWeb下載文件並將結果添加到緩存中。

1.添加CachedDownloads類,並且定義方法

    class CachedDownloads
    {
        /// <summary>
        /// 將下載在操作的結果保存在線程安全集合cachedDownloads中
        /// </summary>
        static ConcurrentDictionary<string, string> cachedDownloads = new ConcurrentDictionary<string, string>();

        /// <summary>
        /// 以字符串的形式異步下載所請求的資源
        /// </summary>
        /// <param name="address">地址</param>
        /// <returns></returns>
        public static Task<string> DownloadStringAsync(string address)
        {
            //首先嘗試從緩存中檢索內容。
            string content;
            if (cachedDownloads.TryGetValue(address, out content))
            {
                return Task.FromResult<string>(content);
            }
            //如果結果不在緩存中,那么使用異步方法下載字符串,並將其添加到緩存中
            return Task.Run(async () =>
            {
                content = await new WebClient().DownloadStringTaskAsync(address);
                cachedDownloads.TryAdd(address, content);
                return content;
            });
        }
    }

​ 該類定義了一個ConcurrentDictionary集合用以保存下載結果,並且定義了DownloadStringAsync接受一個字符串地址,該方法內首先嘗試從緩存中檢索內容,如果結果不在緩存中,那么使用異步方法下載字符串,並將其添加到緩存中,返回Task<string>結果。

2.Main方法:

    class Program
    {
        static void Main(string[] args)
        {
            //需要下載的url集合
            string[] urls = new string[] {
                "https://www.cnblogs.com",
                "http://msdn.microsoft.com",
                "http://www.microsoft.com"
            };

            //用於計時下載操作
            Stopwatch stopwatch = new Stopwatch();
            //開始計時下載url所需要的時間
            stopwatch.Start();
            var downloads = from url in urls
                            select CachedDownloads.DownloadStringAsync(url);
            Task.WhenAll(downloads).ContinueWith(results =>
            {
                stopwatch.Stop();
                //打印下載的字符數和運行時間。
                Console.WriteLine("Retrieved {0} characters. Elapsed time was {1} ms.",
                  results.Result.Sum(result => result.Length),
                  stopwatch.ElapsedMilliseconds);
            }).Wait();


            //重新計時
            stopwatch.Restart();
            downloads = from url in urls
                        select CachedDownloads.DownloadStringAsync(url);
            Task.WhenAll(downloads).ContinueWith(results =>
            {
                stopwatch.Stop();

                //打印下載的字符數和運行時間。
                Console.WriteLine("Retrieved {0} characters. Elapsed time was {1} ms.",
                   results.Result.Sum(result => result.Length),
                   stopwatch.ElapsedMilliseconds);
            }).Wait();

            Console.ReadKey();
        }
    }

測試結果:

測試結果

3.結論

​ 此示例計算兩次下載多個字符串所需的時間。第二組下載操作應該比第一組少花費時間,因為結果保存在緩存中。該FromResult方法使DownloadStringAsync創建方法任務<TResult>持有這些預先計算的結果對象。

​ 我對“預先”的理解為已經知道的結果,當一個方法需要返回Task 對象時,如果有一種情況TResult已經預先知道,讓么就可以使用Task.FromResult(TResult)方法返回Task 對象。

​ 參考資料:

  1. How to: Create Pre-Computed Tasks

  2. Task.FromResult(TResult) Method


    埼玉鎮帖

qiyu


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM