私が本当にやりたいことは、2 つの非同期操作を次々と完了することだけです。例えば
Web サイト X をダウンロードします。それが完了したら、Web サイト Y をダウンロードします。
私が本当にやりたいことは、2 つの非同期操作を次々と完了することだけです。例えば
Web サイト X をダウンロードします。それが完了したら、Web サイト Y をダウンロードします。
両方のオブザーバブルから SelectMany を実行します (ToAsync を使用して操作を IObservable として取得します)、LINQ select many (または構文シュガーを使用) と同様です。
var result =
from x in X
from y in Y
select new { x, y }
他にもオプションがありますが、それは特定のシナリオによって異なります。
たぶん、次の線に沿った何か:
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");
私自身、このような提案は好きではありませんが...
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