2013-02-13 42 views
2

我正在将一个大的Txt文档读入WPF应用程序中,以进行一些严重的交换/替换操作。这些文件实际上是3D STP模型,因此它们相当大,但我正在将它们作为该项目的原始文本进行处理。这些文件被读入列表以避免多次打开它们,并使比较更容易。将.TXT实时读入列表框

无论如何,我试图让列表框动态滚动,因为行被添加到它,ala控制台窗口,因此用户可以看到发生了一些事情,因为计算可能需要一些时间取决于文件大小。我还添加了一个进度条来计数,因为总行数是通读的。

我的进度条和ListBox似乎都不会随着工作进度而更新。最终的输出完全落在列表框中,同时进度条从0-max开始。

这是我在做什么的要点,这是相当简单:

foreach (string Line in OriginalSTPFile.Lines) 
    { 
     string NewLine = EvaluateString(Line); //string the modified to whatever here 
     pBar.Value++; //increment progressbar 

     OutputWindow.Items.Add(NewLine); //add line to the ListBox 
    } 

我只想列表框中的进度条实时的进展变化进行更新。我试过使用:

Dispatcher.BeginInvoke(new Action(() => OutputWindow.Items.Add(NewLine)); 

但是得到了同样的结果。我需要更复杂的多线程方法吗?我假设第一种方法会起作用,因为我没有产生任何交叉线程异常。

+0

你是什么意思与“实时”的伪代码?什么是相当大的?请同时发布更新进度条的步骤功能。 – 2013-02-13 20:10:25

+0

如同一样,每当一条线被“评估”时,结果立即被打印到列表框中,并且相应地移动演算条。应该在下一行被评估之前发生。现在,该程序暂时挂起,然后所有信息同时出现。 – 2013-02-13 20:13:50

+0

请看我的答案。它肯定会帮助你。 – 2013-02-13 20:43:32

回答

1

Dispatcher.BeginInvoke信号调用Dispatcher线程上的方法。但是,这基本上就像是一条邮件消息,因为在主线程被锁定工作时它不会发生。直到主线程再次可用,它不会以可视方式更新UI,即使您更改了值。

您需要在后台线程中执行该工作。

但是要更新UI,您必须在UI的主线程上这样做。这是WPF的限制。这就是为什么你被引导到分派器。我猜猜有人认为你的工作已经在后台线程上。

要创建一个线程,请使用Thread.Start传递一个委托来执行。如果您使用匿名委托或lambda表达式,则可以引用堆栈中的变量,但请注意,它们将一直存在,直到委托退出。这就是为什么你不能在匿名代理中使用引用变量的原因。

Backgroundworker是一种特殊类型的后台线程。它自动化了工作线程的一些期望(通知完成和更新进度),但是如果没有它,你可以获得相同的结果。

要在线程进程中更新UI,您需要该线程能够访问主UI线程。你可以通过传递一个调度器,引用一个来自匿名委托之外的调度器,或者一个包含调度器的对象。你可以随时读取任何线程上的任何对象的值,因此在另一个线程上通过UIElement访问调度器就没有问题。

要更新用户界面,您可以拨打Dispatcher.BeginInvoke与需要执行工作的委托。

这里的总体方案

class TestProgress 
{ 
    ProgressBar _ProgressBar; 

    void DoWork() 
    { 
     var worker = (Action)(() => 
     { 
      int progress = 0; 
      // do stuff, delta is change in progress 
      progress += delta; 
      _ProgressBar.Dispatcher.BeginInvoke((Action)(() => 
      { 
       _ProgressBar.Value = progress; 
      })); 
     }); 
     Thread.Start(worker); 
    } 
} 
+0

这两个答案都非常好,我希望我可以选择两个!足够的话,除非我在我的DoWork方法中包含Thread.Sleep(1),否则显示仍然不会更新。它在后台执行,我可以移动UI,但不会动态更新。 – 2013-02-13 20:54:48

+1

尝试调用而不是BeginInvoke – 2013-02-13 21:00:09

+0

就是这样!我有很多需要关注多线程的东西!谢谢 – 2013-02-13 21:04:33