Наследование класса задач в C # 4.0 - PullRequest
2 голосов
/ 31 июля 2010

Я пытаюсь запланировать единицу работы для обработки в фоновом режиме и получить результат. Первоначально я думал о расширении класса Task и планировании этого экземпляра пользовательской задачи. (думая о Future и Runnable из Java) Каждая задача инкапсулирует множество свойств для ввода / вывода. Несколько задач обрабатываются одновременно и полностью автономны.

Однако я не могу найти каких-либо примеров этого, поэтому я начинаю сомневаться, что это правильный путь. Может кто-нибудь привести пример правильного выполнения этого с System.Threading.Tasks

Ответы [ 2 ]

1 голос
/ 31 июля 2010

Вам не нужно создавать подкласс 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.

0 голосов
/ 20 октября 2011

Вы можете использовать другой подход, как я обнаружил. Вы можете создать класс, который инкапсулирует некоторую логику Задачи. А снаружи используйте 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));
                                }
                            }
                        }
                    }
                }


            }
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...