【发布时间】:2010-07-07 21:10:36
【问题描述】:
我是一名使用 .NET 框架的初级开发人员。
我正在处理一个问题,因为当我运行具有大量数据的应用程序时,我的 GUI 冻结。
我有一个网格和一种输出文本框来记录字符串。网格中每条预期到达的消息都有一行。
然后,应用程序接收消息并且网格更新对应于消息的行中的单元格。另外,我在文本框中写了一个字符串,其中包含有关消息的信息。
例如,文本框会有如下消息:
10:23:45 Message 1 arrived and the result is OK
10:23:45 Message 2 arrived and the result is OK
10:23:45 Message 3 arrived and the result is FAIL
10:23:45 Message 4 arrived and the result is OK
10:23:46 Message 5 arrived and the result is OK
....
网格会是这样的:
MESSAGE_ID | RESULT <------- HEADER
Message_1 | OK
Message_2 | FAIL
Message_3 | OK
Message_4 | OK
Message_5 | OK
Message_6 | Waiting
Message_7 | Waiting
....
问题是当我在很短的时间内收到几条消息时,GUI 会冻结,因为它一直在更新网格和文本框。它会冻结,直到所有消息都到达并且网格和文本输出被更新。
您知道是否有某种方法可以使 GUI 不冻结?使用多个线程来更新 GUI?
我认为这不是 BackgroundWorker,因为 GUI 是应该完成工作的,但也许我错了。
编辑1:
其实我有两个线程:
1) 主线程。它是 GUI,它有一个 BlockingQueue。
private BlockingQueue _guiQueue = new BlockingQueue(1000);
2) 线程1 它接收消息,在收到消息后做一些工作,然后将结果排队并发送到 GUI:
_guiQueue.Enqueue(new UpdateResult(_message.Name, _message.Result));
我正在使用 BlockingQueues,这些: http://www.codeproject.com/KB/recipes/boundedblockingqueue.aspx
一旦主线程收到消息,它基本上会更新 Grid 和输出文本框,仅此而已。
public MainThread(IMainForm mainView)
{
// presenter
_mainView = mainView;
....
// Blocking queues
_guiQueue = new BlockingQueue(1000);
....
// Timer
logger.Debug("Initializing Timer");
_timer = new DispatcherTimer();
_timer.Interval = TimeSpan.FromMilliseconds(10);
// Call handleMessages method everytime the timer wakes up
_timer.Tick += HandleMessages;
_timer.Start();
...
// Order Passing Thread
logger.Debug("Launching OPThread");
_orderPassingThread = new OPThread(_OPQueue, _commonObjects);
_orderPassingThreadProcess = new Thread(new ThreadStart(_orderPassingThread.OPThreadProcess));
_orderPassingThreadProcess.Start();
...
}
private void HandleMessages(Object sender, EventArgs args)
{
Presenter.Messages.Message message;
while ((message = _guiQueue.Dequeue(10)) != null)
{
switch (message.MessageType)
{
case messageTypes.updateResult:
UpdateResult updateStepMsg = (UpdateResult) message;
_mainView.updateStepResult(updateStepMsg.Name, updateStepMsg.Result); // updates Grid and text box
break;
....
default:
break;
}
}
}
}
问题是当我在一秒钟左右收到多条消息时。
例如,我有一个停止按钮来停止一切,但由于 GUI 处于冻结状态,所以无法单击它
谢谢!
PS:我用的是DevExpress,网格是XtraGrid,输出文本框是memoEdit控件
【问题讨论】:
-
你能告诉我们产生后台线程的代码吗?以及包含整个 while 循环的方法?
-
添加了该代码。队列是这些:codeproject.com/KB/recipes/…
-
如果这是Java,我可能会在以下位置同步GUI线程策略:_mainView.updateStepResult(updateStepMsg.Name, updateStepMsg.Result) 可能,您可以从:stackoverflow.com/questions/530211/…
-
“此类型的任何公共静态(在 Visual Basic 中为共享)成员都是线程安全的。不保证任何实例成员都是线程安全的”是什么意思。对于 DispatcherTimer 类? msdn.microsoft.com/en-us/library/…这家伙提到他的实现在beta.codeproject.com/KB/threads/WaitPulse.aspx中是安全的
标签: .net user-interface devexpress