2009-03-24 2 views
3

Я должен иметь возможность сохранять файл, к сожалению, он потенциально может быть очень большим, поэтому его сохранение может занять несколько минут. Поскольку мне нужно сделать это из потока GUI, я не хочу блокировать выполнение GUI. Я думал о попытке операции сохранения в отдельном потоке, чтобы позволить основному потоку GUI продолжать выполнение.C# потоки для манипулирования файлами

Есть ли хороший (простой) способ создать новый поток, сохранить файл и уничтожить поток без каких-либо неприятных побочных эффектов ?!

Должно быть сказано, что мне НИКОГДА не пришлось использовать потоки, чтобы я был полным новичком! Любая помощь будет принята с благодарностью!

ответ

5

BackgroundWorker (как предложено Фредериком) является хорошим выбором, особенно если вы хотите сообщить о прогрессе в пользовательском интерфейсе во время сохранения. A search for BackgroundWorker tutorial получает много хитов, поэтому вы должны следовать одному из них, чтобы вы начали.

Остерегайтесь: можно ли каким-либо образом изменить структуру данных, которую вы пытаетесь сохранить из потока пользовательского интерфейса? Если это так, вы должны отключить эти аспекты пользовательского интерфейса во время сохранения - он (возможно!) Будет плохим, чтобы быть на полпути путем сохранения данных, а затем позволить пользователю изменить часть этого. Если вам удастся эффективно передавать данные в фоновый поток, а затем не трогать его из потока пользовательского интерфейса, это значительно облегчит вашу жизнь.

+0

Я бы подумал, что было бы лучше сделать копию данных и передать их второму рабочему, а не отключать части пользовательского интерфейса. – Quibblesome

+0

@Quarrelsome: Иногда. Это действительно зависит от ситуации, и ожидает ли пользователь, что результатом будет моментальный снимок или нет. Также в некоторых случаях сделать полный снимок может быть очень сложно, так как лучше иметь надежную, но слегка раздражающую программу, чем сломанную :) –

5

Возможно, вы можете использовать компонент BackGroundWorker, так как он немного абстрагирует часть Threading.

3

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

void SaveMyFile(object state) 
{ 
    // SaveTheFile 
} 

и называя его

ThreadPool.QueueUserWorkItem(SaveMyFile); 

будет делать то, что вы хотите.

0

или вы могли бы использовать делегатов старых друзей.

3

Я бы рекомендовал делать асинхронные операции ввода-вывода. Это немного проще настроить и не требует, чтобы вы сами создавали новые потоки.

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

Что вы делаете, используя функции в BeginWrite/BeginRead и EndWrite/EndRead, которые доступны в классе Stream.

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

Внутри функции обратного вызова вы вызываете EndWrite и очищаете поток и проверяете наличие ошибок.

BeginWrite не будет блокировать, что означает, что если он вызван из обработчика событий, этот поток может завершить этот обработчик и продолжить обработку большего количества событий (например, других событий GUI).

using System; 
using System.IO; 
using System.Text; 

class Program 
    { 
     private static FileStream stream; 
     static void Main(string[] args) 
     { 
      stream = new FileStream("foo.txt", 
            FileMode.Create, 
            FileAccess.Write); 

      const string mystring = "Foobarlalala"; 
      ASCIIEncoding encoding = new ASCIIEncoding(); 
      byte[] data = encoding.GetBytes(mystring); 
      Console.WriteLine("Started writing"); 
      stream.BeginWrite(data, 0, data.Length, callback, null); 
      Console.WriteLine("Writing dispatched, sleeping 5 secs"); 
      System.Threading.Thread.Sleep(5000); 
     } 

     public static void callback(IAsyncResult ia) 
     { 
      stream.EndWrite(ia); 
      Console.WriteLine("Finished writing"); 
     } 
    } 
} 

Сон очень важен, потому что нить, которая пишет материал, будет убита, если основная нить будет уничтожена. Это не проблема в графическом приложении, только здесь, в этом небольшом примере.

MSDN имеет pretty good overview о том, как писать этот материал, а также некоторые good articles по программированию асинхронного в целом в случае, если вы идете на backgroundworker или ThreadPool.

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