开发者

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));
                                }
                            }
                        }
                    }
                }


            }
        }
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜