よろしくお願いいたします。
WPFアプリケーションのTPLを使用して、リモートサーバーからファイルをダウンロードしています。UIスレッドで実行される「転送マネージャー」メソッドがあり、そこからバックグラウンドタスクを作成してファイルを個別にダウンロードします。UIを更新するために、バックグラウンドタスクに継続タスクをアタッチします。
問題は次のとおりです。最初のファイルの場合、ダウンロードタスクは期待どおりに新しいスレッドで開始されます。ただし、以降のすべてのダウンロードでは、UIがアプリケーションをロックするのと同じスレッドを使用しています。
私は宿題をし、これに関連する資料を読んだので、この行動を理解できず、自分が間違っていることとそれを修正する方法を判断できません。ヘルプ、ヒント、ポインタ、説明をいただければ幸いです。ありがとう。
デバッグモードからサンプルコードと出力ウィンドウテキストを添付しています。
private void btnNew_Click(object sender, RoutedEventArgs e)
{
// do some work and prepare transfer state object(my custom object)
...
..
iTaskFactory = new TaskFactory
(TaskCreationOptions.LongRunning | TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.None);
// call transfer manager
this.ManageTransfer(null, iDownloadState);
}
private void ManageTransfer(Task antecedent, TransferState ts)
{
if(antecedent == null)
// this is the first invocation of the task from GetNew / Upload methods
{
ts.IsActive = true;
// some code....
}
else if(antecedent.IsFaulted) // check exception on previous task executed
// if there is a fault, then retry the page again
{
// do some error logging....
//retry transferring the same page again
pageToTranfer = ts.PagesTransferred + 1;
}
else
// if the page was successfully transferred
{
//increment transfer count
ts.PagesTransferred += 1;
// update UI.... (as running on UI Thread)
// if all pages are transferred, then exit method. No further tasks to queue
if(ts.PagesTransferred == ts.Pages)
{
return;
}
pageToTranfer = ts.PagesTransferred + 1;
}
Task transferTask; // should run in background thread
// **Problem is that afer first execution**,
// **this also runs on UI Thread!!**
Task continuationTask; // should run in UI thread
localFile = "someName.txt"; //..... work out next file to transfer
serverFile = "someName.txt"; //..... work out next file to transfer
time = DateTime.Now.ToString("hh:mm:ss.ffff"); //.ToShortTimeString();
Debug.WriteLine(time + "starting download :" + pageToTranfer.ToString()
+ " This is Thread: "
+ Thread.CurrentThread.ManagedThreadId.ToString());
transferTask = iTaskFactory.StartNew(() => Download(serverFile, localFile));
continuationTask = transferTask.ContinueWith((t1Task) => ManageTransfer(t1Task, ts)
, TaskScheduler.FromCurrentSynchronizationContext());
}
public bool Download(string aCloudPath, string aLocalPath)
{
time = DateTime.Now.ToString("hh:mm:ss.ffff"); //.ToShortTimeString();
Debug.WriteLine(time + " in background for downloading "
+ aCloudPath + " using thread:"
+ Thread.CurrentThread.ManagedThreadId.ToString());
// code to transfer file... no access to UI or any shared variable
return true;
}
出力ウィンドウ:
10:37:53.2629ダウンロードの開始:1これはスレッドです:8
スレッド:15を使用してfile-01.txtをダウンロードするためのバックグラウンドでの10:37:55.2720
10:37:56.4120ダウンロード開始:2これはスレッドです:8
スレッド:8を使用してfile-02.txtをダウンロードするためのバックグラウンドでの10:38:00.4143
10:38:01.2413ダウンロード開始:3これはスレッドです:8
スレッド:8を使用してfile-03.txtをダウンロードするためのバックグラウンドでの10:38:05.2445
10:38:05.8606ダウンロード開始:4これはスレッドです:8
スレッド:8を使用してfile-04.txtをダウンロードするためのバックグラウンドでの10:38:09.8618
ご覧のとおり、初めてダウンロード機能が期待どおりにバックグラウンドで実行されました。しかしその後もUIスレッドで実行し続けます!! ManagerTranferが同じスレッドで実行され、ダウンロード機能に別のスレッドが使用されることを期待しています。
単純なタスク(つまり、TaskFactoryなし)でもこれを試しましたが、動作は同じです。TaskCreationOptions.LongRunningを設定したので、TPLは関係なく新しいスレッドを開始する必要があります!!!