Асинхронность выполнения задач


На .Net 3.5 с я не имею доступа к ТПЛ. Еще я устала от того, чтобы вручную управлять логика делегата.Тип метод BeginInvoke сценариев каждый раз и я создана для реализации моих собственных задач класс.

Функции она должна поддерживать:

  • запуск параллельного выполнения (используя поток пула потоков)
  • способен ждать результат с определенным таймаутом
  • способен прервать выполнение сказали
  • следует предусмотреть мероприятия для обратных вызовов, чтобы присоединить к

Это моя реализация. Может вы, ребята, пожалуйста, просмотрите его и укажите, если есть какие-либо вопросы, я, возможно, не рассмотрели или, может быть, более эффективные способы, чтобы реализовать некоторые вещи?

public class Task<T>
{
    #region Members
    private IAsyncResult _async;
    private Func<T> _action;
    private Func<T> _innerAction;
    private WaitHandle _waitHandle;
    private Thread _thread;
    private object _completedLock = new object();
    private object _abortLock = new object();
    private T _result;
    private bool _endCalled = false;
    #endregion

    #region Properties
    public object Tag { get; private set; }
    public bool IsCompleted { get; private set; }
    public bool IsRunning { get; private set; }

    public T Result
    {
        get
        {
            if (!_endCalled)
            {
                lock (_completedLock)
                {
                    if (!_endCalled)
                    {
                        try
                        {
                            if (_async != null)
                            {
                                _result = _innerAction.EndInvoke(_async);
                                IsCompleted = true;
                            }
                        }
                        finally
                        {
                            _endCalled = true;
                        }
                    }
                }
            }
            return _result;
        }
    }
    #endregion

    #region Events
    public event EventHandler Completed;
    #endregion

    public Task(Func<T> action, object tag)
        : this(action)
    {
        Tag = tag;
    }

    public Task(Func<T> action)
    {
        _action = action;
        _innerAction = () =>
        {
            try
            {
                _thread = Thread.CurrentThread;
                var result = _action();
                return result;
            }
            finally
            {
                lock (_abortLock)
                {
                    IsRunning = false;
                }
            }
        };
    }

    #region Public Methods
    public void Run()
    {
        if (!IsRunning || IsCompleted)
        {
            lock (_completedLock)
            {
                if (!IsRunning || IsCompleted)
                {
                    ResetState();
                    _async = _innerAction.BeginInvoke(obj => OnCompleted(), null);
                    IsRunning = true;
                    return;
                }
            }
        }
        throw new InvalidOperationException("Task is already running");
    }

    public bool WaitForCompletion(TimeSpan timeout)
    {
        if (IsRunning && !IsCompleted)
        {
            lock (_completedLock)
            {
                if (!IsCompleted)
                {
                    _waitHandle = _async.AsyncWaitHandle;
                    return _waitHandle.WaitOne(timeout);
                }
            }
        }
        return IsCompleted;
    }

    public bool WaitForCompletion(int timeoutMilliseconds)
    {
        return WaitForCompletion(TimeSpan.FromMilliseconds(timeoutMilliseconds));
    }

    public bool Abort()
    {
        bool result = false;
        if (!IsCompleted)
        {
            lock (_abortLock)
            {
                if (!IsCompleted && IsRunning)
                {
                    if (_thread != null)
                    {
                        _thread.Abort();
                    }
                    result = true;
                }
                ResetState();
            }
        }
        return result;
    }
    #endregion

    private void ResetState()
    {
        _async = null;
        _endCalled = false;
        _result = default(T);
        _thread = null;
        IsCompleted = false;
        IsRunning = false;
    }

    private void OnCompleted()
    {
        lock (_completedLock)
        {
            IsCompleted = true;
            if (_waitHandle != null)
            {
                _waitHandle.Close();
                _waitHandle = null;
            }
        }

        if (Completed != null)
        {
            try
            {
                Completed(this, EventArgs.Empty);
            }
            catch
            {
                //We swallow this as there is no way to catch it at an upper level
                //on the execution thread and do something about it.
                //Callbacks should not throw anyway.
            }
        }
    }
}


3228
9
задан 10 мая 2011 в 01:05 Источник Поделиться
Комментарии
2 ответа


  • Вы, возможно, захотите рассмотреть вопрос о замене плит (выполняется/IsCompleted) с единой государственной перечисления.

  • Некоторые государственные проверки использования _abortLock в то время как другие используют _completedLock.


    1. Если метод abort() вызывается на задание, которое еще не началось,

    2. переключение контекста происходит только перед ResetState() называется,

    3. второй поток вызывает метод run() и новая внутренняя резьба начинается,

    4. еще одно переключение контекста происходит, и первый поток возобновляет называть ResetState()

    Да, несколько спутников должны быть согласованны, чтобы это произошло ... но все же.


  • Если метод run() вызывается последующим прервать() перед внутренней резьбы на самом деле начнется, то _thread может быть null, в результате чего нить не быть прервана и противоречивом состоянии. (опять-таки с Луны.)

  • Аборт не немедленно завершить поток, вы должны дождаться его завершения, прежде чем сбросить состояние.

  • Я не уверен, прерывая поток пула потоков-это хорошая идея.

  • Вы поставить метку в одном из конструкторов, но я не вижу его в любом месте.

5
ответ дан 11 мая 2011 в 12:05 Источник Поделиться

Может быть, эта ссылка поможет вам:


Если вы загружаете реактивной расширения для .Чистая 3.5SP1 от http://msdn.microsoft.com/en-us/devlabs/ee794896.aspxвы найдете System.Threading.dll сборка... Что содержит TPL для .Нетто 3.5.

ЗЫ: ГХ страница была перемещена, чтобы: http://msdn.microsoft.com/en-us/data/gg577609

3
ответ дан 11 мая 2011 в 07:05 Источник Поделиться