Thanks for your time and assistance in advance.
I am using TPL from WPF application to download files from a remote server. I have a 'transfer manager' method that runs on the UI thread, from which I create background Tasks to download files individually. I attach continuation tasks on the background tasks to update UI.
Problem is: for first file, the download tasks is starting on a new thread as expected. But for all subsequent downloads, it is using the same thread as UI locking up the application.
I have done my homework, read relevant material on this and hence I am unable to understand this behaviour, determine what I am doing wrong and how to fix it. Any help, tips, pointers, explanation is appreciated. Thanks.
I am attaching sample code and output window text from debug mode.
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;
}
Output Window:
10:37:53.2629 starting download :1 This is Thread: 8
10:37:55.2720 in background for downloading file-01.txt using thread:15
10:37:56.4120 starting download :2 This is Thread: 8
10:38:00.4143 in background for downloading file-02.txt using thread:8
10:38:01.2413 starting download :3 This is Thread: 8
10:38:05.2445 in background for downloading file-03.txt using thread:8
10:38:05.8606 starting download :4 This is Thread: 8
10:38:09.8618 in background for downloading file-04.txt using thread:8
As you can see, first time the download function ran in background as expected. But after that it keeps on running in UI Thread!! I am expecting ManagerTranfer to run in the same thread and a different Thread to be used for Download function.
I have tried this with simple Tasks (i.e. without TaskFactory) as well, but the behaviour is same. I have set TaskCreationOptions.LongRunning, so TPL should start a new thread regardless!!!