<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          .NET并發(fā)編程-函數(shù)式組合器

          共 8552字,需瀏覽 18分鐘

           ·

          2021-04-22 08:45

          寫給普通:

          有問題就會有答案

          本系列學(xué)習(xí)在.NET中的并發(fā)并行編程模式,實戰(zhàn)技巧

          最近兩周有點拖更,主要去弄了個大黑耗子。也出現(xiàn)了不少事情,才發(fā)現(xiàn)和生活相比,工作真的是最簡單快樂的事了。所以就繼續(xù)聊點開心的,把.NET并發(fā)編程啃完。




          本小節(jié)介紹以函數(shù)式的風(fēng)格來管理異常,特別是異步操作。使用函數(shù)組合器常見復(fù)雜任務(wù),提高編寫并發(fā)計算和處理副作用的能力


          1、錯誤處理


          在命令式編程中一般直接使用try/catch錯誤處理,在函數(shù)式編程中操作失敗不會返回null,而是包裝成一個成功或失敗的結(jié)構(gòu)表達形式。


          1.1 用于錯誤處理的函數(shù)組合器


          前面也已經(jīng)嘗試了Retry和Otherwise用于在異常情況下的應(yīng)用邏輯的異步Task操作。主要是通過利用Task類型的Status和Exception屬性來提供錯誤處理。

           

          Image image = await Retry(async () =>  await DownloadImageAsync("Bugghina001.jpg").Otherwise(async () => await DownloadImageAsync("Bugghina002.jpg")),5, TimeSpan.FromSeconds(2));

          1.2 Task<Option<T>>處理錯誤


          Option類型強制了開發(fā)人員必須編寫邏輯來檢查值是否存在,從而減輕了null值和error值的許多問題。Option類型的結(jié)果要么是Some,要么是None。

           

          static async Task<Option<Image>> DownloadOptionImage(string blobReference) {    try    {        var container = await Helpers.GetCloudBlobContainerAsync().ConfigureAwait(false);        CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobReference);        using (var memStream = new MemoryStream())        {            await blockBlob.DownloadToStreamAsync(memStream).ConfigureAwait(false);            return Some(Image.FromStream(memStream));            }    }    catch (Exception)    {        return None;         }}

           

          Option類型和Match高階函數(shù)組合使用

           DownloadOptionImage("Bugghina001.jpg").Map(opt => opt.Match(                some: image => image.Save("ImageFolder\Bugghina.jpg"),                none:()=>Log("下載失敗")                )); 

           

          1.3 使用Result類型保留異常信息


          上面使用Task<Option>所有的異常都返回None,沒有記錄詳細的異常信息。Result類型定義如下

             public struct Result<T>    {        public T Ok { get; }                    public Exception Error { get; } 

          public bool IsFailed { get => Error != null; } public bool IsOk => !IsFailed;

          public Result(T ok) { Ok = ok; Error = default(Exception); } public Result(Exception error) { Error = error; Ok = default(T); }

          public R Match<R>(Func<T, R> okMap, Func<Exception, R> failureMap) => IsOk ? okMap(Ok) : failureMap(Error);

          public void Match(Action<T> okAction, Action<Exception> errorAction) { if (IsOk) okAction(Ok); else errorAction(Error); }

          public static implicit operator Result<T>(T ok) => new Result<T>(ok); // #D public static implicit operator Result<T>(Exception error) => new Result<T>(error); // #D

          public static implicit operator Result<T>(Result.Ok<T> ok) => new Result<T>(ok.Value); //#D public static implicit operator Result<T>(Result.Failure error) => new Result<T>(error.Error); }

          public static class Result { public struct Ok<L> { internal L Value { get; } internal Ok(L value) { Value = value; }

          }

          public struct Failure { internal Exception Error { get; } internal Failure(Exception error) { Error = error; } } }

          public static class ResultExtensions { public static Result.Ok<T> Ok<T>(T value) => new Result.Ok<T>(value); public static Result.Failure Failure(Exception error) => new Result.Failure(error);

          public static async Task<Result<T>> TryCatch<T>(Func<Task<T>> func) { try { return await func(); } catch (Exception ex) { return ex; } }

          public static Task<Result<T>> TryCatch<T>(Func<T> func) => TryCatch(() => Task.FromResult(func()));

          public static async Task<Result<R>> SelectMany<T, R>(this Task<Result<T>> resultTask, Func<T, Task<Result<R>>> func) { Result<T> result = await resultTask.ConfigureAwait(false); if (result.IsFailed) return result.Error; return await func(result.Ok); }

          public static async Task<Result<R>> Select<T, R>(this Task<Result<T>> resultTask, Func<T, Task<R>> func) { Result<T> result = await resultTask.ConfigureAwait(false); if (result.IsFailed) return result.Error; return await func(result.Ok).ConfigureAwait(false); } public static async Task<Result<R>> Match<T, R>(this Task<Result<T>> resultTask, Func<T, Task<R>> actionOk, Func<Exception, Task<R>> actionError) { Result<T> result = await resultTask.ConfigureAwait(false); if (result.IsFailed) return await actionError(result.Error); return await actionOk(result.Ok); }

          public static async Task<Result<T>> ToResult<T>(this Task<Option<T>> optionTask) where T : class { Option<T> opt = await optionTask.ConfigureAwait(false);

          if (opt.IsSome()) return Ok(opt.Value); return new Exception(); }

          public static async Task<Result<R>> OnSuccess<T, R>(this Task<Result<T>> resultTask, Func<T, Task<R>> func) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsFailed) return result.Error; return await func(result.Ok).ConfigureAwait(false); }

          public static async Task<Result<T>> OnFailure<T>(this Task<Result<T>> resultTask, Func<Task> func) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsFailed) await func().ConfigureAwait(false); return result; }

          public static async Task<Result<R>> Bind<T, R>(this Task<Result<T>> resultTask, Func<T, Task<Result<R>>> func) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsFailed) return result.Error; return await func(result.Ok).ConfigureAwait(false); }

          public static async Task<Result<R>> Map<T, R>(this Task<Result<T>> resultTask, Func<T, Task<R>> func) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsFailed) return result.Error;

          return await TryCatch(() => func(result.Ok)); }

          public static async Task<Result<R>> Match<T, R>(this Task<Result<T>> resultTask, Func<T, R> actionOk, Func<Exception, R> actionError) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsFailed) return actionError(result.Error); return actionOk(result.Ok); }

          public static async Task<Result<T>> Ensure<T>(this Task<Result<T>> resultTask, Func<T, Task<bool>> predicate, string errorMessage) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsFailed || !await predicate(result.Ok).ConfigureAwait(false)) return result.Error; return result.Ok; }

          public static async Task<Result<T>> Tap<T>(this Task<Result<T>> resultTask, Func<T, Task> action) { Result<T> result = await resultTask.ConfigureAwait(false);

          if (result.IsOk) await action(result.Ok).ConfigureAwait(false);

           

          使用Result將使代碼看起來更易讀一些,任務(wù)邏輯內(nèi)部不需要人為的去封裝錯誤返回結(jié)果。直接使用Result相同處理。例如下面這樣

           

          static Result<byte[]> ReadFile(string path){    if(System.IO.File.Exists(path))    {        return System.IO.File.ReadAllBytes(path);    }    else    {        return new FileNotFoundException(path);    }}

           

          2、函數(shù)式組合器


          TPL內(nèi)置的異步組合器。例如Task.Run,Task.WhenAll和Task.WhenAny等。這些內(nèi)置組合器可以很容易地擴展來實現(xiàn)有用的組合器以組合和構(gòu)建更復(fù)雜的基于任務(wù)的模式。

           

           

           

           

           

           

          to be contiued!

          下集:使用TPL Dataflow的并行工作流與代理編程?




          寫給普通:

          有問題就會有答案



          瀏覽 54
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  VA毛片 | 五月天激情视频网站 | 香蕉视频做爱的 | 国产传媒一区 | 四虎影院永久在线 |