Вы можете использовать другой подход, как я обнаружил. Вы можете создать класс, который инкапсулирует некоторую логику Задачи. А снаружи используйте ConcurrencyDictionary для управления им. Вот черновик ...
public class ContentManagerTask
{
public ContentManagerTask(DownloadResult downloadResult)
{
TaskResult = downloadResult;
this.BeginTask(downloadResult);
}
public DownloadResult TaskResult;
/// <summary>Starts a background task to compute a value and returns immediately.</summary>
private void BeginTask(DownloadResult downloadResult)
{
downloadResult.Result = false;
Task task = new Task(() =>
{
var result = Download(downloadResult);
lock (this)
{
TaskResult = result;
}
});
task.Start();
}
private DownloadResult Download(DownloadResult downloadResult)
{
try
{
// Logic to download file
int i = 0;
while (i < 10)
{
Thread.Sleep(10000);
i++;
string log = string.Format("Content Manager: Task - {4} - (Time {0}; ID: {1}) is downloading this File: '{2}' from URL: '{3}' ", DateTime.Now.ToString(), downloadResult.ContentItem.ID, downloadResult.ContentItem.FileName, downloadResult.ContentItem.URL, i.ToString());
CustomLogger.CustomLogger.WriteNormalLog(log);
}
downloadResult.Result = true;
}
catch (Exception ex)
{
#region Error
LogEntry l = new LogEntry();
l.Message = string.Format("Error: {0}", ex.Message);
l.Title = "MyApp Error";
l.Categories.Add(Category.General);
l.Priority = Priority.Highest;
l.ExtendedProperties.Add("Method", "DownloadError Download()");
if (ex.InnerException != null) l.ExtendedProperties.Add("InnerException", ex.InnerException.Message);
CustomLogger.CustomLogger.WriteErrorLog(l);
#endregion
downloadResult.Error = ex;
}
return downloadResult;
}
}
И внешний код
C oncurrentDictionary<Guid, ContentManagerTask> contentManagerWorkArea = new ConcurrentDictionary<Guid, ContentManagerTask>();
private void MyManagerJob()
{
bool moreToDo = true;
while (moreToDo)
{
if (contentManagerState)
{
Thread.Sleep(1000);
//var s = sequences.
#region Start tasks to download content data
// Each task should check if there is a file. If there is not a file it should be downloaded.
List<ContentItem> contentItems = (List<ContentItem>)App.Current.Properties["ContentItems"];
foreach (var ci in contentItems)
{
if (ci.IsDownloadable)
{
// Delete finished tasks
var finishedTasks = (from c in contentManagerWorkArea where c.Value.TaskResult.Result == true select c).AsParallel();
foreach (var finishedTask in finishedTasks)
{
ContentManagerTask ctm;
contentManagerWorkArea.TryRemove(finishedTask.Key, out ctm);
CustomLogger.WriteNormalLog(string.Format("Content Manager: Finished Task has been deleted. Time: {0}; ID: {1}; File: {2}; URL: {3} ", DateTime.Now.ToString(), ctm.TaskResult.ContentItem.ID, ctm.TaskResult.ContentItem.FileName, ctm.TaskResult.ContentItem.URL));
ctm = null;
}
// Add new task
var unfinishedTasks = (from c in contentManagerWorkArea where c.Value.TaskResult.Result == false select c).AsParallel();
if (unfinishedTasks.Count() == 0) // Area is empty we have to add the first task
{
DownloadResult dr = new DownloadResult();
dr.ContentItem = ci;
ContentManagerTask contentManagerTask = new ContentManagerTask(dr);
contentManagerWorkArea.TryAdd(ci.ID, contentManagerTask);
CustomLogger.WriteNormalLog(string.Format("Content Manager: New Task has been added. Time: {0}; ID: {1}; File: {2}; URL: {3} ", DateTime.Now.ToString(), ci.ID, ci.FileName, ci.URL));
}
else // Area is not empty and we have to check if some of the tasks are the same we have to insert in
{
foreach (var unfinishedTask in unfinishedTasks)
{
if (!unfinishedTask.Value.TaskResult.ContentItem.ID.Equals(ci.ID))
{
DownloadResult dr = new DownloadResult();
dr.ContentItem = ci;
ContentManagerTask contentManagerTask = new ContentManagerTask(dr);
contentManagerWorkArea.TryAdd(ci.ID, contentManagerTask);
CustomLogger.WriteNormalLog(string.Format("Content Manager: New Task has been added. Time: {0}; ID: {1}; File: {2}; URL: {3} ", DateTime.Now.ToString(), ci.ID, ci.FileName, ci.URL));
}
}
}
}
}
}
}
}