C # темы для манипулирования файлами - PullRequest
3 голосов
/ 24 марта 2009

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

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

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

Ответы [ 5 ]

5 голосов
/ 24 марта 2009

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

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

5 голосов
/ 24 марта 2009

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

3 голосов
/ 24 марта 2009

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

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

То, что вы делаете, - это использование BeginWrite / BeginRead и EndWrite / EndRead , доступных в классе Stream.

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

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

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

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

3 голосов
/ 24 марта 2009

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

void SaveMyFile(object state)
{
    // SaveTheFile
}

и вызывая его с

ThreadPool.QueueUserWorkItem( SaveMyFile );

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

0 голосов
/ 24 марта 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...