2009-07-21 4 views
51

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

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

+0

Просто хотел упомянуть - есть два способа выполнения асинхронных вызовов: с потоками и с делегатами. –

+0

Это очень просто. Вы создаете делегат. Назначьте свою функцию, а затем выполните асинхронный вызов. [This] (http://msdn.microsoft.com/en-us/magazine/cc301332.aspx) статья описывает это очень хорошо (он также учит вас тому, что является делегатом). –

+1

Ссылка не работает для меня ?? –

ответ

4

Вот две ссылки о многопоточности в C#

Я начала читать о BackgroundWorker class

+0

Спасибо за ответ, можно ли это сделать без потоков, может быть с делегатами? –

+0

Вы можете использовать BeginInvoke(), но это вызывает и другой поток. Действительно, взгляните на BackgroundWorker - он прост в использовании и предоставляет уведомление, когда задание выполняется. – tanascius

74

Вы должны использовать делегатов и 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

+18

Обратите внимание, что вместо объявления и использования 'SomeFunctionDelegate' вы можете просто использовать« Action »и аналогично« Func »для недействительных методов. –

+2

новое действие (имя метода) .BeginInvoke (1, "текст", null, null); –

+0

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

1

ThreadPool.QueueUserWorkItem это самый быстрый способ получить процесс, протекающий в другом потоке.

Помните, что объекты UI имеют «сходство потоков» и не могут быть доступны из любого потока, отличного от того, который их создал.

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

+0

Если кто-то нуждается в доступе к элементам пользовательского интерфейса, созданным в другом потоке (исключения с перекрестными потоками), см. Это замечательное сообщение: http://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed -from-a-thread-other-than-the-t –

6

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

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

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. Обратите внимание, что это только , затронутый после завершения асинхронной задачи. Это означает, что ничто другое не может помешать выполнению задач внутренней работы, и это не может помешать чему-либо еще.

+2

То, что «задача Async, закончившаяся с {0}», не печатается после завершения задачи async ... – Jacob

+2

Plz исправить ваше утверждение «Каждый раз, когда вы делаете что-то асинхронное, вы используете отдельный поток ». Это неверно. Проверьте [Asynchrony in C# 5.0, часть четвертая: это не волшебство] (http://blogs.msdn.com/b/ericlippert/archive/2010/11/04/asynchrony-in-c-5-0-part-four- it-s-not-magic.aspx) –

+0

Это логический процесс _separate_, даже если физически один и тот же поток можно повторно использовать. –

0

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

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

Background Worker

4

В 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(); 
} 
18

попробовать этот метод

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"); }); 
Смежные вопросы