C# Rx-如何从任务创建IObservable,以便取消订阅取消任务?

C# Rx-如何从任务创建IObservable,以便取消订阅取消任务?,c#,system.reactive,C#,System.reactive,我是新来的,所以请容忍我 我想将任务包装在一个IObservable中。到目前为止一切顺利: Task<T> task = Task.Factory.StartNew(...); IObservable<T> obs = task.ToObservable(); 现在,我要做的是在观察者取消订阅时发出取消任务的信号: var cancel = new CancellationToken(); Task<T> task = Task.Factory.Start

我是新来的,所以请容忍我

我想将任务包装在一个IObservable中。到目前为止一切顺利:

Task<T> task = Task.Factory.StartNew(...);
IObservable<T> obs = task.ToObservable();
现在,我要做的是在观察者取消订阅时发出取消任务的信号:

var cancel = new CancellationToken();
Task<T> task = Task.Factory.StartNew(..., cancel);

IObservable<T> obs = task.ToObservable(); //there should be a way to tie the cancel token
                                          //to the IObservable (?)

IDisposable disposable = obs.Subscribe(...);
Thread.Sleep(1000);
disposable.Dispose(); // this should signal the task to cancel
我该怎么做


FWIW以下是生成此切线的场景:

以下是我能想到的最简单的方法,使用Observable。创建:

我在评论中暗示的最初方式实际上相当冗长:

static IObservable<int> SomeRxWork()
{
    return Observable.Create<int>(async (o, token) =>
    {
        try
        {
            o.OnNext(await SomeAsyncWork(token));
            o.OnCompleted();
        }
        catch (OperationCanceledException)
        {
        }
        catch (Exception ex)
        {
            o.OnError(ex);
        }
    });
}

下面是我能想到的最简单的方法,使用Observable.Create:

我在评论中暗示的最初方式实际上相当冗长:

static IObservable<int> SomeRxWork()
{
    return Observable.Create<int>(async (o, token) =>
    {
        try
        {
            o.OnNext(await SomeAsyncWork(token));
            o.OnCompleted();
        }
        catch (OperationCanceledException)
        {
        }
        catch (Exception ex)
        {
            o.OnError(ex);
        }
    });
}

假设您有这样一种方法:

Task<Gizmo> GetGizmoAsync(int id, CancellationToken cancellationToken);
您可以将其转换为IObservable,其中订阅开始任务,取消订阅通过使用以下命令取消任务

IObservable<Gizmo> observable = Observable.FromAsync(
    cancellationToken => GetGizmoAsync(7, cancellationToken));

// Starts the task:
IDisposable subscription = observable.Subscribe(...);

// Cancels the task if it is still running:
subscription.Dispose();

假设您有这样一种方法:

Task<Gizmo> GetGizmoAsync(int id, CancellationToken cancellationToken);
您可以将其转换为IObservable,其中订阅开始任务,取消订阅通过使用以下命令取消任务

IObservable<Gizmo> observable = Observable.FromAsync(
    cancellationToken => GetGizmoAsync(7, cancellationToken));

// Starts the task:
IDisposable subscription = observable.Subscribe(...);

// Cancels the task if it is still running:
subscription.Dispose();

使用Observable.Create重载之一可能是最简单的,它允许您传入Func。但是请注意,这将在订阅时而不是之前启动新任务。我认为在订阅时启动任务实际上是对的:而且,我偶然发现了可观察的。使用取消令牌创建重载,但尚未找到一个令人信服的示例-您可以编写一个或链接到一个,如果你知道的话?顺便说一句:多亏了IntelliSense,我才遇到过这些重载;在您提出此问题时的MSDN文档中,我不确定Observable.FromAsync方法是否存在。但是,现在这些是正确的方法。使用一个可观察的。创建重载,让您传入Func,可能是最简单的方法。但是请注意,这将在订阅时而不是之前启动新任务。我认为在订阅时启动任务实际上是对的:而且,我偶然发现了可观察的。使用取消令牌创建重载,但尚未找到一个令人信服的示例-您可以编写一个或链接到一个,如果你知道的话?顺便说一句:多亏了IntelliSense,我才遇到过这些重载;在您提出此问题时的MSDN文档中,我不确定Observable.FromAsync方法是否存在。然而,现在这些是正确的方法,关键是返回新的CompositeDisposablesub,new CancellationDisposablects。太好了!谢谢你给出了一个清晰的答案。关键是返回新的CompositeDisposablesub,new CancellationDisposablects。太好了!谢谢你的回答。