我有一个处理与外部服务通信的后台线程。每次后台线程收到一条消息时,我都想将它传递给UI线程以供进一步处理(向用户显示)。在ui线程中执行委托(使用消息泵)
目前我已经做了一个线程安全的消息队列,定期存储在Timer.Tick中并填充后台线程。但是这个解决方案是次优的。
你知道如何使用消息泵将事件从后台线程传递到UI线程吗?
我有一个处理与外部服务通信的后台线程。每次后台线程收到一条消息时,我都想将它传递给UI线程以供进一步处理(向用户显示)。在ui线程中执行委托(使用消息泵)
目前我已经做了一个线程安全的消息队列,定期存储在Timer.Tick中并填充后台线程。但是这个解决方案是次优的。
你知道如何使用消息泵将事件从后台线程传递到UI线程吗?
有几种技术。
Control.Invoke()
(等人)
我发现这个的WinForms技术始终好用,但要知道,有你需要得到正确的一些微妙的规则。我试图捕获一个通用的工作实现,它能够正确处理代码段posted elsewhere on stackoverflow中的规则。
我没有必要向太多使用这种技术,所以我真的不能说什么意义了。但是,您应该知道它存在。我相信这是确保在特定线程的上下文中调用某些东西的有效方法,即使该线程是而不是 ui线程。
如果你使用WPF工作时,WPF控件一般会从DispatcherObject
获得供应Dispatcher对象。这是一种比Control.Invoke()
功能更丰富的同步技术,但也更复杂。请务必仔细阅读文档。
您可以使用Control.Invoke并使用委托。委托将在创建控件的线程上执行。
这是正确的方式来做到这一点。 – 2009-07-15 16:37:42
只需确保不要将Delegate.Invoke()与Control.Invoke()混淆Control.Invoke()就是你想要的 – STW 2009-07-15 17:03:30
如果您的GUI线程被阻塞,不处理任何消息,你可以使用Application.DoEvents
迫使GUI线程来处理该线程等待所有的消息。
要抽取消息的控制线程,当然你可以使用Control.BeginInvoke
或Control.Invoke
方法,但要注意,Control.Invoke
将阻止如果Control
的拥有的线程当前阻止。
您可以使用WPF调度程序(类分派器)在WindowsBase.dll了。
以下是在MSMQ中使用WPF中的Dispacther对象的示例。
的背后代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Messaging;
namespace MSMQGui
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string queueName = @".\private$\MyFunWithMSMQ";
private MessageQueue queue = null;
public MainWindow()
{
InitializeComponent();
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName,false);
queue = new MessageQueue(queueName);
queue.ReceiveCompleted += receiveCompleted;
}
private void btnAddMessage_Click(object sender, RoutedEventArgs e)
{
string message = txtMessage.Text;
txtMessage.Text = String.Empty;
queue.Send(message);
MessageBox.Show("Message :" + message + " sent");
}
private void Populate(object sender, RoutedEventArgs e)
{
try
{
queue.BeginReceive(TimeSpan.FromSeconds(1)) ;
}
catch (MessageQueueException)
{
MessageBox.Show("No message available");
}
}
private void receiveCompleted(object source, ReceiveCompletedEventArgs e)
{
try
{
var message=queue.EndReceive(e.AsyncResult);
Action<string> addMessage= (string msg) => {
ListViewItem item = new ListViewItem();
item.Content = msg;
lsvMessages.Items.Add(item);
};
this.Dispatcher.Invoke(addMessage, message.Body as string);
}
catch (MessageQueueException)
{
MessageBox.Show("No message available");
}
}
}
}
的XAML:
<Window x:Class="MSMQGui.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="3*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="1*"></RowDefinition>
<RowDefinition Height="9*"></RowDefinition>
<RowDefinition Height="1*"></RowDefinition>
</Grid.RowDefinitions>
<!-- First row -->
<Label x:Name="lblMessage"
Content="Message:"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
HorizontalContentAlignment="Right"
Grid.Column="0" Grid.Row="0"
></Label>
<StackPanel Grid.Column="1" Grid.Row="0" Orientation="Horizontal">
<TextBox x:Name="txtMessage" Width="200" HorizontalAlignment="Left" ></TextBox>
<Button x:Name="btnAddMessage" Content="Add message" Margin="5,0,0,0" Click="btnAddMessage_Click"></Button>
</StackPanel>
<!-- Second row -->
<ListView x:Name="lsvMessages" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,5,0,0">
</ListView>
<!-- Third row-->
<Button x:Name="btnPopulate" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Right" Click="Populate" Content="Get messages from queque" Margin="5,0,0,0"></Button>
</Grid>
</Window>
的WinForms?或wpf? – 2009-07-15 16:29:44
winforms,但我想听两个 – 2009-07-15 17:34:39