首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >来自Task.Continuewith的新任务(在单独的线程上运行)

来自Task.Continuewith的新任务(在单独的线程上运行)
EN

Stack Overflow用户
提问于 2012-10-08 05:24:54
回答 1查看 787关注 0票数 2

谢谢你提前给我时间和帮助。

我使用来自WPF应用程序的TPL从远程服务器下载文件。我有一个运行在UI线程上的“传输管理器”方法,我从它创建后台任务来单独下载文件。我在后台任务上附加继续任务以更新UI。

问题是:对于第一个文件,下载任务正按预期在一个新线程上启动。但是对于所有后续下载,它使用的线程与UI锁定应用程序的线程相同。

我已经做了家庭作业,阅读了相关的材料,因此我无法理解这种行为,确定我做错了什么,以及如何纠正它。任何帮助,提示,指点,解释都是非常感谢的。谢谢。

我是附加样例代码和输出窗口文本从调试模式。

代码语言:javascript
复制
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 10:37:55.2720在后台使用线程:15下载文件-01.txt 10:37:56.4120开始下载:2这是线程:8 10:38:00.4143在后台使用线程:8下载文件-02.txt 10:38:01.2413开始下载:3这是线程:8 10:38:05.2445在后台使用线程:8下载文件-03.txt 10:38:05.8606开始下载:4这是线程:8 10:38:09.8618在后台使用线程:8下载文件-04.txt

如您所见,第一次像预期的那样在后台运行。但在此之后,它继续在UI Thread!!中运行,我希望ManagerTranfer运行在同一个线程中,并使用不同的线程作为下载功能。

我也尝试过简单的任务(即没有TaskFactory),但是行为是一样的。我已经设置了TaskCreationOptions.LongRunning,所以TPL应该启动一个新线程!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-10-08 06:22:23

您使用的调度器是在currentSync上下文中运行任务的调度器,它将在UI线程上与在同一调度程序上调度的其他任务一起运行您的任务。为了在分离的线程上运行任务,您应该使用另一个调度器来实现taskscheduler类并相应地生成线程。

调度器类似于使用在这个岗位上,但是您也必须对调度程序进行一定程度的定制,我可以看到您也在使用当前线程,这在实现自己的调度程序时可能不那么容易。另一方面,您可以始终使用一些有用的ParallelTaskExtensions,而QueuedtaskScheduler提供了一些有用的实现,可以在这方面使用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12775759

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档