提前感谢您的时间和帮助。
我正在使用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这是Thread:8
10:37:55.2720在后台使用thread:15
下载file-01.txt10:37:56.4120开始下载:2这是主题:8
10:38:00.4143在后台使用thread:8
下载file-02.txt10:38:01.2413开始下载:3这是主题:8
10:38:05.2445在后台使用thread:8
下载file-03.txt10:38:05.8606开始下载:4这是主题:8
10:38:09.8618在后台使用thread:8
下载file-04.txt
如您所见,第一次下载功能按预期在后台运行。但之后它继续在UI Thread !! 中运行 我期待ManagerTranfer在相同的线程和不同的线程中运行以用于下载功能。
我也尝试过简单的任务(即没有TaskFactory),但行为是一样的。我已经设置了TaskCreationOptions.LongRunning,所以TPL应该开始一个新线程,无论如何!!!
答案 0 :(得分:1)
您正在使用的调度程序是在currentSync上下文中运行任务的调度程序,它将依次在UI线程上运行您的任务以及在同一调度程序上调度的其他任务。为了在单独的线程上运行你的任务,你应该使用另一个调度器来实现taskscheduler类并相应地创建线程。
类似的调度程序使用 in this post ,但是您还需要对调度程序进行一定级别的自定义,因为我可以看到您正在使用当前线程,在实现自己的调度程序时可能并不那么容易。另一方面,您总是可以使用一些有用的ParallelTaskExtensions和QueuedtaskScheduler提供一些可以在这方面使用的有用实现。