Подтвердить что ты не робот

Как создать асинхронный метод

У меня есть простой метод в моем приложении С#, он выбирает файл с FTP-сервера и анализирует его и сохраняет данные в БД. Я хочу, чтобы он был асинхронным, чтобы пользователь выполнял другие операции над приложением, как только разбор выполняется, он должен получить сообщение о том, что "Parsing is done".

Я знаю, что это может быть достигнуто с помощью асинхронного вызова метода, но Я не знаю, как это сделать. Кто-нибудь может мне помочь?

4b9b3361

Ответ 1

Вам нужно использовать делегаты и метод BeginInvoke, который они содержат, для асинхронного запуска другого метода. A конец метода, выполняемого делегатом, вы можете уведомить пользователя. Например:

class MyClass
{
    private delegate void SomeFunctionDelegate(int param1, bool param2);
    private SomeFunctionDelegate sfd;

    public MyClass()
    {
        sfd = new SomeFunctionDelegate(this.SomeFunction);
    }

    private void SomeFunction(int param1, bool param2)
    {
        // Do stuff

        // Notify user
    }

    public void GetData()
    {
        // Do stuff

        sfd.BeginInvoke(34, true, null, null);
    }
}

Читайте на http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

Ответ 2

попробуйте этот метод

public static void RunAsynchronously(Action method, Action callback) {
    ThreadPool.QueueUserWorkItem(_ =>
    {
        try {
            method();
        } 
        catch (ThreadAbortException) { /* dont report on this */ } 
        catch (Exception ex) {
        }
        // note: this will not be called if the thread is aborted
        if (callback!= null) callback();
    });
}

Использование:

RunAsynchronously( () => { picks file from FTP server and parses it}, 
       () => { Console.WriteLine("Parsing is done"); } );

Ответ 3

В любое время, когда вы делаете что-то асинхронное, вы используете отдельный поток, либо новый поток, либо один из пула потоков. Это означает, что все, что вы делаете асинхронно, должно быть очень осторожным в отношении взаимодействия с другими потоками.

Один из способов сделать это - поместить код для потока async (назовем его потоком "A" ) вместе со всеми его данными в другой класс (назовите его классом "A" ). Убедитесь, что поток "A" только обращается к данным в классе "A". Если нить "А" касается только класса "А" , и ни одна другая нить не касается данных класса "А" , то есть еще одна проблема:

public class MainClass
{
    private sealed class AsyncClass
    {
        private int _counter;
        private readonly int _maxCount;

        public AsyncClass(int maxCount) { _maxCount = maxCount; }

        public void Run()
        {
            while (_counter++ < _maxCount) { Thread.Sleep(1); }
            CompletionTime = DateTime.Now;
        }

        public DateTime CompletionTime { get; private set; }
    }

    private AsyncClass _asyncInstance;
    public void StartAsync()
    {
        var asyncDoneTime = DateTime.MinValue;
        _asyncInstance = new AsyncClass(10);
        Action asyncAction = _asyncInstance.Run;
        asyncAction.BeginInvoke(
            ar =>
                {
                    asyncAction.EndInvoke(ar);
                    asyncDoneTime = _asyncInstance.CompletionTime;
                }, null);
        Console.WriteLine("Async task ended at {0}", asyncDoneTime);
    }
}

Обратите внимание, что единственная часть AsyncClass, которая коснулась извне, - это общедоступный интерфейс, а единственной частью данных, которая является данными, является CompletionTime. Обратите внимание, что это происходит только после завершения асинхронной задачи. Это означает, что ничто другое не может помешать выполнению задач внутренней работы и не может вмешиваться в что-либо еще.

Ответ 5

В Asp.Net я использую много статических методов для выполнения заданий. Если это просто работа, где мне нужен без ответа или статус, я делаю что-то простое, как показано ниже. Как вы можете видеть, я могу выбрать вызов ResizeImages или ResizeImagesAsync в зависимости от того, хочу ли я ждать завершения или нет.

Объяснение кода: Я использую http://imageresizing.net/ для изменения размера/обрезки изображений, а метод SaveBlobPng - для сохранения изображений в Azure (облако), но так как это не имеет значения для этой демонстрации, я не включил этот код. Это хороший пример трудоемких задач, хотя

private delegate void ResizeImagesDelegate(string tempuri, Dictionary<string, string> versions);
private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
    ResizeImagesDelegate worker = new ResizeImagesDelegate(ResizeImages);
    worker.BeginInvoke(tempuri, versions, deletetemp, null, null);
}
private static void ResizeImages(string tempuri, Dictionary<string, string> versions)
{
    //the job, whatever it might be
    foreach (var item in versions)
    {
        var image = ImageBuilder.Current.Build(tempuri, new ResizeSettings(item.Value));
        SaveBlobPng(image, item.Key);
        image.Dispose();
    }
}

Или для потоковой передачи, поэтому вам не нужно беспокоиться о делегатах

private static void ResizeImagesAsync(string tempuri, Dictionary<string, string> versions)
{
    Thread t = new Thread (() => ResizeImages(tempuri, versions, null, null));
    t.Start(); 
}

Ответ 6

ThreadPool.QueueUserWorkItem - это самый быстрый способ запустить процесс в другом потоке.

Имейте в виду, что объекты пользовательского интерфейса имеют "сходство потоков" и не могут быть доступны из любого потока, отличного от того, который их создал.

Итак, помимо проверки ThreadPool (или с использованием модели асинхронного программирования через делегатов), вам нужно проверить Dispatchers ( wpf) или InvokeRequired (winforms).

Ответ 7

В конце вам придется использовать какую-то резьбу. Принцип работы в основном заключается в том, что вы запускаете функцию с новым потоком, и она будет работать до конца функции.

Если вы используете Windows Forms, тогда хорошая обертка, которую они имеют для этого, вызывает фоновый рабочий. Он позволяет работать в фоновом режиме без блокировки формы пользовательского интерфейса и даже обеспечивает способ общения с формами и обновления событий обновления.

Фоновый работник