我正在尝试安排一个工作单元在后台处理,并产生结果。最初我正在考虑扩展 Task 类,并安排自定义任务的该实例。(从 Java 中考虑 Future 和 Runnable)每个任务都封装了多个用于输入/输出的属性。多个任务同时处理,并且是完全自主的。
但是,我找不到任何这样做的例子,所以我开始怀疑这是正确的方法。有人可以提供使用 System.Threading.Tasks 正确执行此操作的示例
我正在尝试安排一个工作单元在后台处理,并产生结果。最初我正在考虑扩展 Task 类,并安排自定义任务的该实例。(从 Java 中考虑 Future 和 Runnable)每个任务都封装了多个用于输入/输出的属性。多个任务同时处理,并且是完全自主的。
但是,我找不到任何这样做的例子,所以我开始怀疑这是正确的方法。有人可以提供使用 System.Threading.Tasks 正确执行此操作的示例
您不需要子类化Task
. 只需实例化一个Task
对象并为其提供要在构造函数中执行的方法。
以下示例计算一个值并将其与一个标志一起存储在一个字段中,以指示操作已完成:
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;
}
当然,在您检索结果的其他代码中,您必须在检查_taskFinished
和之前锁定同一个对象_taskResult
。
您可以使用我发现的另一种方法。您可以创建封装一些任务逻辑的类。而外部使用 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;
}
}
和外部代码
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));
}
}
}
}
}
}
}
}