Шаблон проектирования асинхронного программирования - PullRequest
4 голосов
/ 10 июня 2011

Я работаю над небольшой технической платформой для CF.NET, и у меня вопрос: как мне написать асинхронную часть?Прочитайте много вещей на MSDN, но мне не ясно.

Итак, вот код:

public class A
{
    public IAsyncResult BeginExecute(AsyncCallback callback)
    {
        // What should I put here ?
    }

    public void EndExecute()
    {
        // What should I put here ?
    }

    public void Execute()
    {
        Thread.Sleep(1000 * 10);
    }
}

Если кто-то может мне помочь ...

Спасибо!

Ответы [ 4 ]

7 голосов
/ 10 июня 2011

Вы можете использовать делегата:

public class A
{
    public void Execute()
    {
        Thread.Sleep(1000 * 3);
    }
}

class Program
{
    static void Main()
    {
        var a = new A();
        Action del = (() => a.Execute());
        var result = del.BeginInvoke(state =>
        {
            ((Action)state.AsyncState).EndInvoke(state);
            Console.WriteLine("finished");
        }, del);
        Console.ReadLine();
    }
}

ОБНОВЛЕНИЕ:

Как указано в разделе комментариев, здесь приведен пример реализации:

public class A
{
    private Action _delegate;
    private AutoResetEvent _asyncActiveEvent;

    public IAsyncResult BeginExecute(AsyncCallback callback, object state)
    {
        _delegate = () => Execute();
        if (_asyncActiveEvent == null)
        {
            bool flag = false;
            try
            {
                Monitor.Enter(this, ref flag);
                if (_asyncActiveEvent == null)
                {
                    _asyncActiveEvent = new AutoResetEvent(true);
                }
            }
            finally
            {
                if (flag)
                {
                    Monitor.Exit(this);
                }
            }
        }
        _asyncActiveEvent.WaitOne();
        return _delegate.BeginInvoke(callback, state);
    }

    public void EndExecute(IAsyncResult result)
    {
        try
        {
            _delegate.EndInvoke(result);
        }
        finally
        {
            _delegate = null;
            _asyncActiveEvent.Set();
        }
    }

    private void Execute()
    {
        Thread.Sleep(1000 * 3);
    }
}

class Program
{
    static void Main()
    {
        A a = new A();
        a.BeginExecute(state =>
        {
            Console.WriteLine("finished");
            ((A)state.AsyncState).EndExecute(state);
        }, a);
        Console.ReadLine();
    }
}
1 голос
/ 10 июня 2011

Вам не нужно делать ничего особенного, потому что вызывающий должен вызывать вам метод async,

Он определяет нового делегата, указывающего на ваш метод, и использует .net для асинхронного вызова вашего метода.

0 голосов
/ 10 июня 2011

Если вы хотите выполнить фрагмент кода асинхронно, вы должны использовать BackgroundWorker. Если, конечно, код, который вы вызываете, изначально не поддерживает асинхронную операцию. Так же, как методы чтения / записи или сервисные вызовы.

Если вы хотите уведомить, что асинхронная операция завершена, используйте делегат или обратный вызов события.

0 голосов
/ 10 июня 2011

В BeginExecute вы должны запустить асинхронную операцию (возможно, запустить выполнение в отдельном потоке) и вернуться как можно быстрее. Execute должен вызвать AsyncCallback в конце всех операций, чтобы тот, кто использует асинхронную операцию, узнал и получил результат. EndExecute должен остановить ранее запущенную асинхронную операцию (возможно, прервать поток, запущенный BeginExecute).
Без подробностей это лучшее, что я могу сделать.

...