我遇到了一个问题,当我的应用程序处理大量数据时,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));
我正在使用阻塞队列,这些队列如下: http://www.codeproject.com/KB/recipes/boundedblockingqueue.aspx 主线程接收到消息后,只更新格子和输出文本框,不做其他事情。
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控件。