2

私が本当にやりたいことは、2 つの非同期操作を次々と完了することだけです。例えば

Web サイト X をダウンロードします。それが完了したら、Web サイト Y をダウンロードします。

4

3 に答える 3

2

両方のオブザーバブルから SelectMany を実行します (ToAsync を使用して操作を IObservable として取得します)、LINQ select many (または構文シュガーを使用) と同様です。

var result = 
from x in X
from y in Y
select new { x, y }  

他にもオプションがありますが、それは特定のシナリオによって異なります。

于 2010-03-01T17:09:37.190 に答える
1

たぶん、次の線に沿った何か:

    static IObservable<DownloadProgressChangedEventArgs> CreateDownloadFileObservable(string url, string fileName)
    {
       IObservable<DownloadProgressChangedEventArgs> observable =
           Observable.CreateWithDisposable<DownloadProgressChangedEventArgs>(o =>
        {
            var cancellationTokenSource = new CancellationTokenSource();
            Scheduler.TaskPool.Schedule
            (
                () =>
                {

                    Thread.Sleep(3000);
                    if (!cancellationTokenSource.Token.IsCancellationRequested)
                    {
                        WebClient client = new WebClient();
                        client.DownloadFileAsync(new Uri(url), fileName,fileName);


                        DownloadProgressChangedEventHandler prgChangedHandler = null;
                        prgChangedHandler = (s,e) =>
                            {                                                   
                                o.OnNext(e);
                            };


                        AsyncCompletedEventHandler handler = null;
                        handler = (s, e) =>
                        {
                            prgChangedHandler -= prgChangedHandler;                            
                            if (e.Error != null)
                            {
                                o.OnError(e.Error);
                            }
                            client.DownloadFileCompleted -= handler;
                            o.OnCompleted();
                        };
                        client.DownloadFileCompleted += handler;
                        client.DownloadProgressChanged += prgChangedHandler;
                    }
                    else
                    {
                        Console.WriteLine("Cancelling download of {0}",fileName);
                    }
                }
            );
            return cancellationTokenSource;
        }
        );
       return observable;
    }

    static void Main(string[] args)
    {

        var obs1 = CreateDownloadFileObservable("http://www.cnn.com", "cnn.htm");
        var obs2 = CreateDownloadFileObservable("http://www.bing.com", "bing.htm");

        var result = obs1.Concat(obs2);
        var subscription = result.Subscribe(a => Console.WriteLine("{0} -- {1}% complete ",a.UserState,a.ProgressPercentage), e=> Console.WriteLine(e.Message),()=> Console.WriteLine("Completed"));
        Console.ReadKey();
        subscription.Dispose();
        Console.WriteLine("Press a key to exit");
        Console.ReadKey();
}

CreateDownloadFileObservableをWebClientの拡張メソッドに変換しWebClient client = new WebClient();、メソッド定義から削除すると、クライアントは次のようになります。

WebClient c = new WebClient();
c.CreateDownloadFileObservable ("www.bing.com","bing.htm");
于 2010-03-30T05:46:42.973 に答える
1

私自身、このような提案は好きではありませんが...

2 つの操作を連続して実行する必要がある場合は、それらを連続して実行します (メインとは異なるスレッドで実行できます)。

それでもコード内でタスクを分離したい場合は、System.Parallel からの新しい構成が適切です。

var task1 = Task.Factory.StartNew (() => FirstTask());
var task2 = task1.ContinueWith (frst => SecondTask ());

そして、これが system.reactive を理解する方法である場合は、Observable.GenerateInSequence を試してください - しかし、それは確かにやり過ぎです。observable は enumerable に対応するものであり、同様の方法 (データの繰り返し) で使用することをお勧めします。非同期操作を実行するためのツールではありません。

編集: 私が間違っていて、Richard が正しかったことを認めたいと思います - 私の返信の時点で、私は RX に完全に慣れていませんでした。RX は、非同期操作を開始する最も自然な方法だと思います。それでも、リチャードの答えは少し不十分です。次のようにする必要があります。

var result =  
from x in XDownload.ToAsync()() 
from y in YDownload.ToAsync()() 
select y   
于 2010-03-02T03:41:34.727 に答える