2010-03-23 2 views
1

У меня есть класс, который в основном хранит файлы в amazon s3. Вот как это выглядит (упрощенный)Вызов асинхронного void. - шаблон, основанный на событиях, или другой метод?

public class S3FileStore 
{ 
    public void PutFile(string ID, Stream content) 
     { 
      //do stuff 
     } 
} 

В моем клиенте приложения, я хочу, чтобы быть в состоянии назвать:

var s3 = new() S3FileStore(); 
s3.PutFile ("myId", File.OpenRead(@"C:\myFile1")); 
s3.PutFile ("myId", File.OpenRead(@"C:\myFile2")); 
s3.PutFile ("myId", File.OpenRead(@"C:\myFile3")); 

Я хочу, чтобы это асинхронная операция - Я хочу S3FileStore для обработки этого (я не хочу, чтобы мой вызывающий абонент должен был запускать PutFile асинхронно, так сказать), но я хочу, чтобы улавливать исключения/рассказывать, завершена ли операция для каждого файла.

Я смотрел на события на основе вызовов асинхронными, особенно это: http://blogs.windowsclient.net/rendle/archive/2008/11/04/functional-shortcuts-2-event-based-asynchronous-pattern.aspx

Однако, я не могу видеть, как назвать мой метод PutFile (Недействительными)?

Есть ли лучшие примеры?

ответ

1

BackgroundWorker базовый класс может быть стоит посмотреть, а также пул потоков:

ThreadPool.QueueUserWorkItem(delegate 
    { 
     s3.PutFile ("myId", File.OpenRead(@"C:\myFile1")); 
    }); 

Это в основном то, что вы могли бы сделать с Action/шаблон BeginInvoke. С BeginInvoke вы также получаете IAsyncResult, на котором вы можете позвонить .WaitOne(), чтобы заблокировать текущий поток до завершения операции, если вам это нужно. Вы должны вызвать новый BeginInvoke для каждого файла, который вы хотите сохранить.

Если вам нужно сделать, это часто, более сложная версия может использовать очереди в сочетании с BackgroundWorker, например .:

public sealed class S3StoreLikePutFileWorker<TYourData> : BackgroundWorker 
{ 
    private AutoResetEvent WakeUpEvent = new AutoResetEvent(false); 

    private Queue<TYourData> DataQueue = new Queue<TYourData>(); 

    private volatile bool StopWork = false; 

    public void PutFile(TYourData dataToWrite) 
    { 
     DataQueue.Enqueue(dataToWrite); 
     WakeUpEvent.Set(); 
    } 

    public void Close() 
    { 
     StopWork = true; 
     WakeUpEvent.Set(); 
    } 

    private override void OnDoWork(DoWorkEventArgs e) 
    { 
     do 
     { 
      // sleep until there is something to do 
      WakeUpEvent.WaitOne(); 
      if(StopWork) break; 

      // Write data, if available 
      while(DataQueue.Count > 0) 
      { 
       TYourData yourDataToWrite = DataQueue.Dequeue(); 
       // write data to file 
      } 
     } 
     while(!StopWork); 
    } 
} 

В зависимости от того, сколько сложности вам нужно.

BackgroundWorker поддерживает обратную связь о ходе работы (набор WorkerReportsProgress = true; в конструкторе), и вы также можете добавить пользовательское событие для сообщений об ошибках, если это необходимо:

// create a custom EventArgs class that provides the information you need 
public sealed class MyEventArgs : EventArgs { 
    // Add information about the file 
} 

// ... define the event in the worker class ... 
public event EventHandler<MyEventArgs> ErrorOccured; 

// ... call it in the worker class (if needed) ... 
if(ErrorOccured != null) ErrorOccured(this, new MyEventArgs(/*...*/)); 

Смежные вопросы