我在WPF中编写代码.首先,我编写了一个单独的项目来测试使用COM端口设备的工作,它运行良好.接下来我决定将它集成到另一个项目中,但是我收到了一个错误.我没有改变代码; 我只是将它复制到一个新的代码文件中.
这段代码效果很好:
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.IO.Ports;
using System.Windows.Threading;
namespace WpfApplication2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
serial.BaudRate = 9600;
serial.Handshake = System.IO.Ports.Handshake.None;
serial.Parity = Parity.None;
serial.DataBits = 8;
serial.StopBits = StopBits.One;
serial.ReadTimeout = 200;
serial.WriteTimeout = 500;
serial.DataReceived …Run Code Online (Sandbox Code Playgroud) 我将可观察字典从视图模型绑定到视图.我使用Caliburn Micro Framework.
视图:
<ListBox Name="Friends"
SelectedIndex="{Binding Path=SelectedFriendsIndex,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Path=SelectedFriend, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}"
Style="{DynamicResource friendsListStyle}"
IsTextSearchEnabled="True" TextSearch.TextPath="Value.Nick"
Grid.Row="2"
Margin="4,4,4,4"
PreviewMouseRightButtonUp="ListBox_PreviewMouseRightButtonUp"
PreviewMouseRightButtonDown="ListBox_PreviewMouseRightButtonDown"
MouseRightButtonDown="ListBox_MouseRightButtonDown"
Micro:Message.Attach="[MouseDoubleClick]=[Action OpenChatScreen()]" >
Run Code Online (Sandbox Code Playgroud)
视图模型类中的代码.
属性看起来像这样:
public MyObservableDictionary<string, UserInfo> Friends
{
get { return _friends; }
set
{
_friends = value;
NotifyOfPropertyChange(() => Friends);
}
}
Run Code Online (Sandbox Code Playgroud)
在Dispatcher计时器中,我每隔3秒调用一个单独的线程新服务方法.
所以我的视图模型的构造函数我有这个:
_dispatcherTimer = new DispatcherTimer();
_dispatcherTimer.Tick += DispatcherTimer_Tick;
_dispatcherTimer.Interval = TimeSpan.FromSeconds(3);
_dispatcherTimer.Start();
_threadDispatcher = Dispatcher.CurrentDispatcher;
Run Code Online (Sandbox Code Playgroud)
而计时器滴答方法在这里:
private void DispatcherTimer_Tick(object sender, EventArgs eventArgs)
{
new System.Threading.Tasks.Task(() =>
{
//get new data from server …Run Code Online (Sandbox Code Playgroud) 我有一个带有多个应用程序Dispatcher(也就是GUI线程,也就是消息泵)的应用程序,以确保GUI的缓慢,无响应部分运行而不会过多地影响应用程序的其余部分.我也经常使用Task.
目前我已经有条件运行Actiona TaskScheduler或a的代码Dispatcher然后Task直接返回或通过手动创建一个使用TaskCompletionSource.然而,这种分裂的个性设计使得处理取消,异常等等都比我想要的复杂得多.我想在任何地方使用Tasks而且DispatcherOperation无处可去.要做到这一点,我需要在调度员上安排任务 - 但是如何?
如何获得TaskScheduler任何给定的Dispatcher?
编辑:在下面的讨论之后,我决定采用以下实现:
public static Task<TaskScheduler> GetScheduler(Dispatcher d) {
var schedulerResult = new TaskCompletionSource<TaskScheduler>();
d.BeginInvoke(() =>
schedulerResult.SetResult(
TaskScheduler.FromCurrentSynchronizationContext()));
return schedulerResult.Task;
}
Run Code Online (Sandbox Code Playgroud) 我想我需要一些帮助来理解Dispatcher Queue.
当新工作到达时,它会在调度程序队列的开头添加,并且当Dispatcher想要处理工作项时,它将从头开始删除.
更一般地说:如果有工作,它将以FIFO方式存储在队列中并且只要没有工作就可以处理.
这里的MSDN文档是指a loop和a frame:
The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.
但在这种情况下,循环在哪里?对我来说,循环是迭代某些东西的东西,当它到达终点时,它会重新开始.
什么是概念frame?根据MSDN文档,框架是队列中工作项的一击?如果这是真的,应该如何使用静态方法Disptatcher.PushFrame()?
最有趣的问题是,是否有任何方法可以获得队列的当前状态,尤其是队列中有多少项.
如果之前调用的方法(以及因此放入Dispatcher队列中)被执行,然后立即将其从队列中删除或者在内部持续另一段时间,它是否成立?
我知道,这么多问题:-)
首先,我需要说我是WPF和C#的菜鸟.应用程序:创建Mandelbrot图像(GUI)我的调度程序完美地适用于这种情况:
private void progressBarRefresh(){
while ((con.Progress) < 99)
{
progressBar1.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
{
progressBar1.Value = con.Progress;
}
));
}
}
Run Code Online (Sandbox Code Playgroud)
当使用以下代码执行此操作时,我收到消息(标题):
bmp = BitmapSource.Create(width, height, 96, 96, pf, null, rawImage, stride);
this.Dispatcher.Invoke(DispatcherPriority.Send, new Action(delegate
{
img.Source = bmp;
ViewBox.Child = img; //vllt am schluss
}
));
Run Code Online (Sandbox Code Playgroud)
我将尝试解释我的程序是如何工作的.我创建了一个新的Thread(因为GUI不响应)来计算像素和颜色.在这个线程(方法)中,我在计算准备好后使用Dispatcher在ViewBox中刷新我的图像.
当我不将计算放在单独的线程中时,我可以刷新或构建我的图像.
在WPF中,由于接口更新的复杂性,我有时必须在短暂的延迟后执行操作.
目前我这样做只是通过:
var dt = new DispatcherTimer(DispatcherPriority.Send);
dt.Tick += (s, e) =>
{
dt.Stop();
//DoStuff
};
dt.Interval = TimeSpan.FromMilliseconds(200);
dt.Start();
Run Code Online (Sandbox Code Playgroud)
但是每次创建一个新的计时器都有点丑陋和开销可能太多(?)从性能的角度来看,最好的做法是什么,即最快地执行?有什么好的方法可以将上面的代码改写成:
this.Dispatcher.BeginInvoke(new Action(delegate()
{
//DoStuff
}), DispatcherPriority.Send,TimeSpan.FromMilliseconds(200));
Run Code Online (Sandbox Code Playgroud)
Timespan是延迟的地方,感谢任何输入:)
我的印象是,dispatcher将遵循排队的操作的优先级,并根据优先级或操作添加到队列的顺序(如果相同的优先级)执行操作,直到我被告知这不是案件的情况WPF UI dispatcher.
有人告诉我,如果UI线程上的操作持续时间较长,则表示数据库读取UI调度程序只是尝试执行队列中的下一组操作.我无法接受它,因此决定编写一个示例WPF应用程序,其中包含一个按钮和三个矩形,点击按钮,矩形填充不同的颜色.
<StackPanel>
<Button x:Name="FillColors" Width="100" Height="100"
Content="Fill Colors" Click="OnFillColorsClick"/>
<TextBlock Width="100" Text="{Binding Order}"/>
<Rectangle x:Name="RectangleOne" Margin="5" Width="100" Height="100" Fill="{Binding BrushOne}" />
<Rectangle x:Name="RectangleTwo" Margin="5" Width="100" Height="100" Fill="{Binding BrushTwo}"/>
<Rectangle x:Name="RectangleThree" Margin="5" Width="100" Height="100" Fill="{Binding BrushThree}"/>
</StackPanel>
Run Code Online (Sandbox Code Playgroud)
并在代码隐藏
private void OnFillColorsClick(object sender, RoutedEventArgs e)
{
var dispatcher = Application.Current.MainWindow.Dispatcher;
dispatcher.BeginInvoke(new Action(() =>
{
//dispatcher.BeginInvoke(new Action(SetBrushOneColor), (DispatcherPriority)4);
//dispatcher.BeginInvoke(new Action(SetBrushTwoColor), (DispatcherPriority)5);
//dispatcher.BeginInvoke(new Action(SetBrushThreeColor), (DispatcherPriority)6);
dispatcher.BeginInvoke(new Action(SetBrushOneColor));
dispatcher.BeginInvoke(new Action(SetBrushTwoColor));
dispatcher.BeginInvoke(new Action(SetBrushThreeColor));
}), (DispatcherPriority)10);
}
private void SetBrushOneColor() …Run Code Online (Sandbox Code Playgroud) 我想设计一个类库并计划使用多线程(即BackgroundWorker).如果我打算将它们绑定到使用前端的库的GUI,我将不得不注意线程上下文,从中为字段进行更新.在我阅读时,将GUI调度程序的引用传递给库并不是一个好主意.但是,如何才能访问将使用该库的应用程序的调度程序?这可能吗?
我尝试Application.Current.Dispatcher并添加了一个引用WindowBase(因为我没有添加的可能性System.Windows),但仍然无法解析调度程序对象.
我有一个WPF应用程序,其中一个线程检查一些值.在某些情况下,我会显示一个弹出窗口Window以显示消息.当我在线程中创建此弹出窗口时,弹出窗口的构造函数抛出异常:
"调用线程必须是STA,因为许多UI组件都需要这个."
我该如何解决这个错误?
这是我创建弹出窗口的代码:
// using System.Threading;
// using System.Windows.Threading;
Thread Messagethread = new Thread(new ThreadStart(delegate()
{
DispatcherOperation DispacherOP =
frmMassenger.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action(delegate()
{
frmMassenger.Show();
}));
}));
Messagethread.Start();
Run Code Online (Sandbox Code Playgroud) 我们偶尔遇到应用程序死锁的情况,并且调度程序似乎与尝试在调度程序上调用的后台线程发生死锁.我没有看到任何一个线程都有任何被锁定的共享资源.后台线程遇到异常,它最终在app域未处理的异常委托中,因为没有人拿起这个异常.这会调用我们的异常处理程序,其任务是确保将异常对话框放到调度程序上.
有人可以建议我可以找出导致死锁的原因吗?
调度程序堆栈遵循并且看起来不同寻常:
*0. System.Windows.Threading.DispatcherSynchronizationContext.Wait (source line information unavailable)
1. System.Threading.SynchronizationContext.InvokeWaitMethodHelper (source line information unavailable)
2. Xceed.Wpf.DataGrid.DeferredOperationManager.Process (source line information unavailable)
3. Xceed.Wpf.DataGrid.DeferredOperationManager.Dispatched_Process (source line information unavailable)
4. System.Windows.Threading.ExceptionWrapper.InternalRealCall (source line information unavailable)
5. System.Windows.Threading.ExceptionWrapper.TryCatchWhen (source line information unavailable)
6. System.Windows.Threading.Dispatcher.WrappedInvoke (source line information unavailable)
7. System.Windows.Threading.DispatcherOperation.InvokeImpl (source line information unavailable)
8. System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext (source line information unavailable)
9. System.Threading.ExecutionContext.runTryCode (source line information unavailable)
10. System.Threading.ExecutionContext.RunInternal (source line information unavailable)
11. System.Threading.ExecutionContext.Run (source line information unavailable)
12. System.Windows.Threading.DispatcherOperation.Invoke (source line information …Run Code Online (Sandbox Code Playgroud)