Inheriting Task class in C# 4.0
I am trying to开发者_运维百科 schedule a unit of work to process in the background, and produce a result. Originally I was thinking about extending the Task class, and scheduling that instance of the custom task. (thinking of Future and Runnable from Java) Each task encapsulates would multiple properties for input/output. Multiple tasks are processed simultaneous, and are completely autonomous.
However, I can't find any examples of doing so, so I am beginning to doubt that that is the correct way to go. Can someone provide the example of doing this correctly with the System.Threading.Tasks
You do not need to subclass Task
. Just instantiate a Task
object and give it the method to be executed in the constructor.
The following example computes a value and stores it in a field along with a flag to indicate that the action is complete:
int _taskResult;
bool _taskFinished;
/// <summary>Starts a background task to compute a value and returns immediately.</summary>
void BeginTask()
{
_taskFinished = false;
Task task = new Task(() =>
{
var result = LongComputation();
lock (this)
{
_taskResult = result;
_taskFinished = true;
}
});
task.Start();
}
/// <summary>Performs the long computation. Called from within <see cref="BeginTask"/>.</summary>
int LongComputation()
{
// Insert long computation code here
return 47;
}
Of course, in your other code that retrieves the result, you’d have to lock on the same object before checking _taskFinished
and _taskResult
.
You can use another approach as I discovered. You can create the class that encapsulates some Task logic. And outside use ConcurrencyDictionary to manage it. Here is some draft...
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;
}
}
And the outside code
ConcurrentDictionary<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));
}
}
}
}
}
}
}
}
精彩评论