谢谢你提前给我时间和帮助。
我使用来自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 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应该启动一个新线程!
发布于 2012-10-08 06:22:23
您使用的调度器是在currentSync上下文中运行任务的调度器,它将在UI线程上与在同一调度程序上调度的其他任务一起运行您的任务。为了在分离的线程上运行任务,您应该使用另一个调度器来实现taskscheduler类并相应地生成线程。
调度器类似于使用在这个岗位上,但是您也必须对调度程序进行一定程度的定制,我可以看到您也在使用当前线程,这在实现自己的调度程序时可能不那么容易。另一方面,您可以始终使用一些有用的ParallelTaskExtensions,而QueuedtaskScheduler提供了一些有用的实现,可以在这方面使用。
https://stackoverflow.com/questions/12775759
复制相似问题