2

よろしくお願いいたします。

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は関係なく新しいスレッドを開始する必要があります!!!

4

1 に答える 1

1

使用しているスケジューラーは、currentSyncコンテキストでタスクを実行するスケジューラーであり、同じスケジューラーでスケジュールされている他のタスクと一緒にUIスレッドでタスクを実行します。別のスレッドでタスクを実行するには、taskschedulerクラスを実装し、それに応じてスレッドを作成する別のスケジューラーを使用する必要があります。

この投稿では同様のスケジューラーが使用されていますが、currentthreadも使用していることがわかるので、スケジューラーに対してもある程度のカスタマイズを行う必要があります。これは、独自のスケジューラーを実装する場合はそれほど簡単ではない可能性があります。 。一方、いつでも役立つParallelTask ​​Extensionsを使用でき、QueuedtaskSchedulerは、この点で使用できるいくつかの便利な実装を提供します。

于 2012-10-08T06:22:23.960 に答える