【问题标题】:How can I realize pattern promise/defered?如何实现模式承诺/延迟?
【发布时间】:2014-11-25 23:59:52
【问题描述】:

我想写一个模式 Promise/Deffered。 最后的完美变体是:

MyObject().CallMethodReturningPromise()
   .done( result => {
       ...something doing;
   } )
   .fail( error => {
       ...error handle;
   } )
   .always( () => {
       ...some code;
   } )

我发现了这个实现 https://bitbucket.org/mattkotsenas/c-promises/overviewhttps://gist.github.com/cuppster/3612000。但是我怎样才能用它来解决我的任务???

【问题讨论】:

  • 出于兴趣,Futures 模式和 Promises 之间有实际区别吗?
  • @Gusdor 术语很模糊 - 这些术语在不同语言中的含义不同。
  • 作为旁注,承诺不是关于 .done .fail.always - 它们更多关于 .then.catch 用于错误处理。见stackoverflow.com/questions/22539815/…
  • 如果您不能使用 Task(因为您被困在旧版本的 .Net 中),我有一个您可能想尝试的 C# promise 实现。 github.com/Real-Serious-Games/C-Sharp-Promise。也可在 nuget 上找到:nuget.org/packages/RSG.Promise
  • @AshleyDavis 周末玩了你的图书馆,喜欢它!提交了一个带有 async/await 示例用法的拉取请求。

标签: c# promise


【解决方案1】:

在我看来,这完全符合tasks

var deferred = Task
    .Factory
    .StartNew(() => /* produce some result (promise) */);

// done
deferred
    .ContinueWith(d => Console.WriteLine(d.Result), TaskContinuationOptions.OnlyOnRanToCompletion);

// fail
deferred
    .ContinueWith(d => Console.WriteLine(d.Exception), TaskContinuationOptions.OnlyOnFaulted);

// always
deferred
    .ContinueWith(d => Console.WriteLine("Do something"));

【讨论】:

  • 有没有办法确保在同一个线程上调用延续?
  • @zumalifeguard:看看这个答案 - stackoverflow.com/a/14058118/580053。简而言之,您通常无法确保这一点。也许你正试图做错事——最好用这种方式描述你想解决的特定问题。
  • 我需要在同一个线程上运行,因为我想从 UI 线程访问资源。
【解决方案2】:

C# 用Tasks 解决了这个问题

任务解决了与 JavaScript 中的 Promise 相同的问题 - 您可以类似地使用它们。但通常情况下,您不应该这样做。

有几个区别:

  • 任务已内置取消。
  • 任务并不总是启动,您可以拥有任务并稍后启动它们。
  • Promise 执行同化,您不能拥有 Promise<Promise<T>>,但您可以在 C# 中拥有任务的任务,并且可能需要在任务上调用 .Unwrap
  • 在 C# 附带的 TPL(任务并行化库)中有一个规范的任务实现,但在 JavaScript 中有许多 Promise 实现。

使用任务

以下是您如何使用 async/await 语法 - 将在 ES7 中添加到 JavaScript 中,并且可以在 ES6 中使用 yield 在某些库中。

async Task Foo(){
    try{
        var res = await myObject.CallMethodReturningTaskOrAsyncMethod();
        doSomethingWithResponse(res);
    } catch(e){
         // handle errors, this will be called if the async task errors
    } finally {
        // this is your .always
    }
}

您也可以use .ContinueWith.then 平行,但它在C# 中非常少见,并且在可以使用await 时通常不受欢迎。你可以了解更多关于using async/await here的信息。

延迟映射到 TaskCompletionSource 实例,Promises 在 C# 中是 Tasks。 Task.WhenAll 用于您使用 $.whenPromise.all 的地方。

你通常写的地方:

a().then(function(res){
    return b(res, "foo");
}).then(function(res2){
    // do work on res2
});

您将在 C# 中执行以下操作:

var res = await a();
var res2 = await b(res, "foo");
// do work on res2.

【讨论】:

  • @Multix 与 try/catch,在 C# 的异步函数中,您可以使用常规 try/catch 并处理异步错误。使用async/await 有助于让您以同步方式编写异步代码。这是一个真正强大的抽象,你会非常喜欢它来自 JavaScript。
  • try/catch reference 包含使用异步的示例以及关于他们如何建议使用异步处理错误和最佳实践的简短教程。
  • @Multix 有什么进展吗?你最后用我的回答解决了吗?
  • @ImBlueDaBaDee 为什么您提出了您的编辑建议?编辑评论应该涵盖这一点。
【解决方案3】:

您可以将异步与 Taskasyncawait 一起使用,如下所示: 注意异步处理不需要使用try catch

 public async Task Method()
   {
     await Task.Run(() =>
            {
                //operations
                Application.Current.Dispatcher.Invoke(() =>
                {
                    //grab the UI Dispatcher if you need
                });
            }).ContinueWith(task =>
            {
                if (task.IsCompleted)
                {
                    //operations success
                }
                else if (task.IsFaulted)
                {
                    //operations failed
                }
            });
        }

【讨论】:

    猜你喜欢
    • 2012-07-08
    • 2016-12-08
    • 2015-03-08
    • 2013-02-21
    • 2015-03-27
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多