【问题标题】:C# threads for file manipulation用于文件操作的 C# 线程
【发布时间】:2010-10-15 04:08:56
【问题描述】:

我必须能够保存一个文件,不幸的是它可能非常大,所以保存它可能需要几分钟。由于我需要从 GUI 线程执行此操作,因此我不想阻止 GUI 执行。我正在考虑在单独的线程上尝试保存操作,以允许主 GUI 线程继续执行。

有没有一种很好(简单)的方法来生成新线程、保存文件并销毁线程而不会产生任何讨厌的副作用?!

必须说我以前从未使用过线程,所以我是一个完全的新手!任何和所有的帮助将不胜感激!

【问题讨论】:

    标签: c# multithreading io


    【解决方案1】:

    我建议使用异步 I/O。设置起来稍微容易一些,并且不需要您自己创建新线程。

    例如,异步编程是您想要写入但不想等待它完成的文件流。您可能希望在完成时收到通知,但您不想等待。

    您所做的是使用 Stream 类中可用的 BeginWrite/BeginReadEndWrite/EndRead 函数。

    在您的方法中,您首先使用您要写入的所有数据调用 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");
            }
        }
    }
    

    睡眠非常重要,因为如果主线程被杀死,正在写东西的线程将被杀死。这在 GUI 应用程序中不是问题,只是在这个小示例中。

    MSDN 有一个关于如何编写这些东西的 pretty good overview,还有一些关于异步编程的 good articles,以防你选择 backgroundworkerThreadPool

    【讨论】:

      【解决方案2】:

      或者你可以使用老朋友代表。

      【讨论】:

        【解决方案3】:

        您的问题可能是有几种很好且简单的方法可以做到这一点。如果你只是想启动文件保存而不担心知道它何时完成,那么有一个方法

        void SaveMyFile(object state)
        {
            // SaveTheFile
        }
        

        并调用它

        ThreadPool.QueueUserWorkItem( SaveMyFile );
        

        会做你想做的。

        【讨论】:

          【解决方案4】:

          BackgroundWorker(由 Frederik 建议)是一个不错的选择,特别是如果您想在保存时向 UI 报告进度。 search for BackgroundWorker tutorial 获得了很多点击,因此您应该能够关注其中一个来帮助您入门。

          有一点需要注意:是否有任何方法可以更改您将尝试从 UI 线程中保存的数据结构?如果是这样,您应该在保存时禁用 UI 的这些方面 - 保存数据的一半(可能!)会很糟糕,然后允许用户更改其中的一些。如果您能够有效地将数据传递给后台线程,而不是从 UI 线程中接触它,那您的生活会轻松很多。

          【讨论】:

          • 我认为制作数据副本并将其交给后台工作人员比禁用部分 UI 更好。
          • @Quarrelsome:有时。这实际上取决于情况,以及用户是否期望结果是快照。同样在某些情况下,拍摄完整的快照可能真的很难做到正确 - 拥有一个可靠但有点烦人的程序比一个坏的更好:)
          【解决方案5】:

          您可以使用 BackGroundWorker 组件,因为它会为您抽象一点线程部分。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-05-28
            • 2020-12-09
            • 1970-01-01
            • 2012-01-02
            • 1970-01-01
            • 2018-11-03
            • 2012-01-01
            • 1970-01-01
            相关资源
            最近更新 更多