线程交互(从一个线程到另一个线程的数据)c#

时间:2012-11-14 19:02:01

标签: c# .net winforms

我需要将信息从扫描数据的线程传递到记录信息线程(写入xml文件)。 它应该看起来像这样:

Application.Run() - 完成

扫描线程 - 完成

写入xlm线程 - ???

UI更新线程 - 我想我做到了

我现在得到了什么:

        private void StartButtonClick(object sender, EventArgs e)
    {
        if (FolderPathTextBox.Text == String.Empty || !Directory.Exists(FolderPathTextBox.Text)) return;
        {
            var nodeDrive = new TreeNode(FolderPathTextBox.Text);
            FolderCatalogTreeView.Nodes.Add(nodeDrive);
            nodeDrive.Expand();
            var t1 = new Thread(() => AddDirectories(nodeDrive));
            t1.Start();
        }
    }

     private void AddDirectories(TreeNode node)
    {
        string strPath = node.FullPath;
        var dirInfo = new DirectoryInfo(strPath);
        DirectoryInfo[] arrayDirInfo;
        FileInfo[] arrayFileInfo;

        try
        {
            arrayDirInfo = dirInfo.GetDirectories();
            arrayFileInfo = dirInfo.GetFiles();
        }
        catch
        {

            return;
        }

      //Write data to xml file
        foreach (FileInfo fileInfo in arrayFileInfo)
        {
            WriteXmlFolders(null, fileInfo);
        }
        foreach (DirectoryInfo directoryInfo in arrayDirInfo)
        {
            WriteXmlFolders(directoryInfo, null);
        }


        foreach (TreeNode nodeFil in arrayFileInfo.Select(file => new TreeNode(file.Name)))
        {
            FolderCatalogTreeView.Invoke(new ThreadStart(delegate { node.Nodes.Add(nodeFil); }));
        }

        foreach (TreeNode nodeDir in arrayDirInfo.Select(dir => new TreeNode(dir.Name)))
        {
            FolderCatalogTreeView.Invoke(new ThreadStart(delegate
                {node.Nodes.Add(nodeDir);
                }));

            StatusLabel.BeginInvoke(new MethodInvoker(delegate
                {
     //UI update...some code here
                }));
            AddDirectories(nodeDir);
        }
    }

      private void WriteXmlFolders(DirectoryInfo dir, FileInfo file)
    {//writing information into the file...some code here}

如何将数据从AddDirectories(递归方法)线程传递给WriteXmlFolders线程?

2 个答案:

答案 0 :(得分:1)

这是一个通用机制,一个线程如何生成另一个线程消耗的数据。无论采用何种方法(阅读:现成的类),您都会使用内部原理保持不变。主要参与者是(注意System.Threading命名空间中有许多可用的锁定类,但这些类最适合这种情况:

AutoResetEvent - 这允许线程进入睡眠模式(不消耗资源),直到另一个线程将其唤醒。 “自动”部分意味着一旦线程被唤醒,该类将被重置,以便下一个Wait()调用将再次使其进入休眠状态,而无需重置任何内容。

ReaderWriterLockReaderWriterLockSlim(如果您使用的是.NET 4,建议使用第二个) - 这只允许一个线程锁定以写入数据,但多个线程可以读取数据。在这种特殊情况下,只有一个阅读线程,但如果有很多,则方法不会有所不同。

// The mechanism for waking up the second thread once data is available
AutoResetEvent _dataAvailable = new AutoResetEvent();

// The mechanism for making sure that the data object is not overwritten while it is being read.
ReaderWriterLockSlim _readWriteLock = new ReaderWriterLockSlim();

// The object that contains the data (note that you might use a collection or something similar but anything works
object _data = null;

void FirstThread()
{
    while (true)
    {
        // do something to calculate the data, but do not store it in _data

        // create a lock so that the _data field can be safely updated.
        _readWriteLock.EnterWriteLock();
        try
        {
            // assign the data (add into the collection etc.)
            _data = ...;

            // notify the other thread that data is available
            _dataAvailable.Set();
        }
        finally
        {
            // release the lock on data
            _readWriteLock.ExitWriteLock();
        }
    }
}

void SecondThread()
{
    while (true)
    {
        object local; // this will hold the data received from the other thread

        // wait for the other thread to provide data
        _dataAvailable.Wait();

        // create a lock so that the _data field can be safely read
        _readWriteLock.EnterReadLock();
        try
        {
            // read the data (add into the collection etc.)
            local = _data.Read();
        }
        finally
        {
            // release the lock on data
            _readWriteLock.ExitReadLock();
        }

        // now do something with the data
    }
}

在.NET 4中,可以避免使用ReadWriteLock并使用其中一个并发安全的集合,例如ConcurrentQueue,这将在内部确保读/写是线程安全的。但是仍然需要AutoResetEvent

.NET 4提供了一种机制,可用于避免偶数AutoResetEvent - BlockingCollection的需要 - 此类提供了线程在数据可用之前休眠的方法。 MSDN page包含有关如何使用它的示例代码。

答案 1 :(得分:1)

如果您将其用作答案

看看生产者消费者。

BlockingCollection Class

How to: Implement Various Producer-Consumer Patterns