简体   繁体   English

用于文件操作的 C# 线程

[英]C# threads for file manipulation

I have to be able to save a file, unfortunatly it can potentially be very large so saving it can potentially take minutes.我必须能够保存一个文件,不幸的是它可能非常大,所以保存它可能需要几分钟。 As I need to do this from a GUI thread I don't want to block the GUI from executing.由于我需要从 GUI 线程执行此操作,因此我不想阻止 GUI 执行。 I was thinking about attempting the save operation on a seperate thread to allow the primary GUI thread to continue executing.我正在考虑在单独的线程上尝试保存操作以允许主 GUI 线程继续执行。

Is there a nice (easy) way to spawn a new thread, save the file, and destroy the thread without any nasty side effects?!有没有一种很好(简单)的方法来生成一个新线程、保存文件并销毁线程而没有任何讨厌的副作用?!

It must be said that I have NEVER had to use threads before so I am a complete novice!必须说我以前从未使用过线程,所以我是一个完全的新手! Any and all help would be greatly appreciated!任何和所有的帮助将不胜感激!

You could maybe use the BackGroundWorker component, as it will abstract a bit the Threading part for you.您也许可以使用 BackGroundWorker 组件,因为它会为您抽象一点 Threading 部分。

BackgroundWorker (as suggested by Frederik) is a good choice, particularly if you want to report progress to the UI while you're saving. BackgroundWorker (由 Frederik 建议)是一个不错的选择,特别是如果您想在保存时向 UI 报告进度。 A search for BackgroundWorker tutorial gets a lot of hits, so you should be able to follow one of those to get you started.搜索 BackgroundWorker 教程获得了很多点击,因此您应该能够按照其中一个来帮助您入门。

One thing to be careful of: would there be any way of changing the data structure that you'll be trying to save from the UI thread?需要注意的一件事是:是否有任何方法可以更改您将尝试从 UI 线程中保存的数据结构? If so, you should disable those aspects of the UI while you're saving - it would (probably,) be bad to be half way through saving the data.如果是这样,您应该在保存时禁用 UI 的这些方面 - 保存数据的一半(可能)会很糟糕。 then allow the user to change some of it, If you can get away with effectively handing off the data to the background thread and then not touching it from the UI thread.然后允许用户更改其中的一些,如果您可以有效地将数据交给后台线程,然后不从 UI 线程触摸它。 that will make your life a lot easier.这将使您的生活更轻松。

Your problem might be that there are several nice and easy ways of doing it.您的问题可能是有几种很好且简单的方法可以做到这一点。 If you just want to set off the file save and not worry about knowing when it has completed, then having a method如果您只想启动文件保存而不担心知道它何时完成,那么有一个方法

void SaveMyFile(object state)
{
    // SaveTheFile
}

and calling it with并用

ThreadPool.QueueUserWorkItem( SaveMyFile );

will do what you want.会做你想做的。

I would recommend doing Asynchronous I/O.我建议做异步 I/O。 It's a little bit easier to set up and doesn't require you to create new threads yourself.设置起来更容易一些,并且不需要您自己创建新线程。

Asynchronous programming is where you have, for example, a file stream you want to write to but does not want to wait for it to finish.例如,异步编程是您想要写入但不想等待它完成的文件 stream 的地方。 You might want to be notified when it's finished but you don't want to wait.您可能希望在完成时收到通知,但您不想等待。

What you do is using the BeginWrite / BeginRead and EndWrite / EndRead functions that are available on the Stream class.您所做的是使用 Stream class 上可用的BeginWrite / BeginReadEndWrite / EndRead函数。

In your method you start by calling BeginWrite with all the data you want to write and also pass in a callback function.在您的方法中,您首先使用您要写入的所有数据调用 BeginWrite,并传入一个回调 function。 This function will be called when BeginWrite has finished.这个 function 将在 BeginWrite 完成时被调用。

Inside the callback function you call EndWrite and clean up the stream and check for errors.在回调 function 中调用 EndWrite 并清理 stream 并检查错误。

BeginWrite will not block which means that if it's called from within an event handler that thread can finish that handler and continue processing more event (such as other GUI events). 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");
        }
    }
}

The sleeping is pretty important because the thread that's writing stuff will be killed if the main thread is killed off.睡眠非常重要,因为如果主线程被杀死,正在写东西的线程将被杀死。 This is not an issue in a GUI application, only here in this small example.这在 GUI 应用程序中不是问题,仅在这个小示例中。

MSDN has a pretty good overview on how to write this stuff, and also some good articles on Asynch programming in general in case you go for the backgroundworker or ThreadPool . MSDN 对如何编写这些东西有很好的概述,还有一些关于异步编程的好文章,以防你 go 为backgroundworkerThreadPool

or u could use old friends delegates.或者你可以使用老朋友代表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM