简体   繁体   English

如何在手动创建的任务中调用异步方法?

[英]How to call an async method inside a manually created task?

I need to implement something like a cold observable object in RxJS (just a standard Observable). 我需要在RxJS中实现类似冷的可观察对象(只是一个标准的可观察对象)。 I need to call an async method inside a task I create myself via constructor (new Task()). 我需要在通过构造函数(new Task())创建自己的任务中调用异步方法。 I need to implement this because before executing any asynchronous code I want to do some stuff which is very specific to my project. 我需要实现它,因为在执行任何异步代码之前,我想做一些非常特定于我的项目的工作。 So I want to recieve a task that is not started yet which I can start manually a little bit later. 因此,我想接收一个尚未开始的任务,稍后可以手动开始。

So far I came to the following decision and to my surprise it isn't working! 到目前为止,我做出了以下决定,令我惊讶的是,这没有用!

class Program
{
    static void Main(string[] args)
    {
        var task1 = CallApi(() => t.Go());
        var task2 =  CallApi2(() => t.Go());


        task1.Start();
        task2.Start();

    }



    public static Task<T> CallApi<T>(Func<Task<T>> function)
    {
        if (function == null)
        {
            throw new ArgumentNullException(nameof(function));
        }


        return new Task<Task<T>>(async () =>
        {
            return await function();
        }).Unwrap();


    }

    public static Task<T> CallApi2<T>(Func<Task<T>> function)
    {
        if (function == null)
        {
            throw new ArgumentNullException(nameof(function));
        }

        var tcs = new TaskCompletionSource<T>();

        var resultTask = new Task<Task<T>>(() =>
        {
            var t = function();

            t.ContinueWith(
                task => {
                    tcs.SetResult(task.Result);
                },
                TaskContinuationOptions.OnlyOnRanToCompletion
            );

            t.ContinueWith(
                task => {
                    tcs.SetCanceled();
                },
                TaskContinuationOptions.OnlyOnCanceled
            );

            t.ContinueWith(
                task => {
                    tcs.SetException(task.Exception);

                },
                TaskContinuationOptions.OnlyOnFaulted
            );
            return tcs.Task;
        });

        return resultTask.Unwrap();

    }
}

It seems that calling Unwrap or using TaskCompletionSource creates a task in a WaitingForActivation state. 似乎调用Unwrap或使用TaskCompletionSource会创建处于WaitingForActivation状态的任务。 And calling Start method on tasks in this state leads me to the exception which is saying: 在这种状态下,对任务调用Start方法会导致出现异常:

Start may not be called on a promise-style task. 在约定样式的任务上可能不会调用启动。

So it's very likely that .NET distinguishes special kind of tasks - promise-style tasks. 因此,.NET很可能区分特殊类型的任务-承诺式任务。

In summary my questions are: 总而言之,我的问题是:

  1. What do these promise-style tasks mean? 这些诺言式任务是什么意思?

  2. How can I do what I want to do? 我该怎么做我想做的事?

Promise style tasks are tasks that are not based on threads, they are based on events, For a TaskCompletionSource the "event" is the act of calling SetResult , SetCanceled or SetException 承诺式任务是不基于线程的任务,它们基于事件,对于TaskCompletionSource ,“事件”是调用SetResultSetCanceledSetException

To receive a task that is not started yet which you can start manually a little bit later, simply hold on to the Func<Task<T>> and you evaluate the function to start up the task at the later point in time. 要接收尚未开始的任务,您可以稍后手动启动它,只需按住Func<Task<T>>然后评估该函数以在以后的时间点启动该任务。 This can be done quite simply. 这可以很简单地完成。

    public void Example()
    {
        Func<Task<T>> func1 = () => t.Go();

        //Do other work

        Task<T> task1 = func1(); //t.Go() is not called until this point then the task starts.

    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM