1

我需要将信息从扫描数据线程传递到记录信息线程(写入 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 线程?

4

2 回答 2

1

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

AutoResetEvent- 这允许线程进入睡眠模式(不消耗资源),直到另一个线程将其唤醒。'auto' 部分意味着一旦线程唤醒,类将被重置,因此下一次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 页面包含有关如何使用它的示例代码。

于 2012-11-14T20:04:18.123 回答
1

如果你用它作为答案

看看生产者消费者。

BlockingCollection 类

如何:实现各种生产者-消费者模式

于 2012-11-14T20:52:20.583 回答