3

我正在尝试安排一个工作单元在后台处理,并产生结果。最初我正在考虑扩展 Task 类,并安排自定义任务的该实例。(从 Java 中考虑 Future 和 Runnable)每个任务都封装了多个用于输入/输出的属性。多个任务同时处理,并且是完全自主的。

但是,我找不到任何这样做的例子,所以我开始怀疑这是正确的方法。有人可以提供使用 System.Threading.Tasks 正确执行此操作的示例

4

2 回答 2

2

您不需要子类化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

于 2010-07-30T21:37:15.177 回答
-1

您可以使用我发现的另一种方法。您可以创建封装一些任务逻辑的类。而外部使用 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));
                                }
                            }
                        }
                    }
                }


            }
        }
    }
于 2011-10-20T19:08:15.730 回答