我有以下示例代码,每次按下按钮时缩放:
XAML:
<Window x:Class="WpfApplication12.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">
<Canvas x:Name="myCanvas">
<Canvas.LayoutTransform>
<ScaleTransform x:Name="myScaleTransform" />
</Canvas.LayoutTransform>
<Button Content="Button"
Name="myButton"
Canvas.Left="50"
Canvas.Top="50"
Click="myButton_Click" />
</Canvas>
</Window>
Run Code Online (Sandbox Code Playgroud)
*的.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
myScaleTransform.ScaleX =
myScaleTransform.ScaleY =
myScaleTransform.ScaleX + 1;
Console.WriteLine("scale {0}, location: {1}",
myScaleTransform.ScaleX,
myCanvas.PointToScreen(GetMyByttonLocation()));
}
private Point GetMyByttonLocation()
{
return new Point(
Canvas.GetLeft(myButton),
Canvas.GetTop(myButton));
}
}
Run Code Online (Sandbox Code Playgroud)
输出是:
scale 1, location: …Run Code Online (Sandbox Code Playgroud) 我的应用程序有问题:在某些时候,SynchronizationContext.Current对主线程变为null.我无法在一个孤立的项目中重现同样的问题.我的真实项目很复杂; 它混合使用Windows窗体和WPF并调用WCF Web服务.据我所知,这些都是可以与SynchronizationContext交互的系统.
这是我孤立项目的代码.我真正的应用程序做了类似的事情.但是,在我的实际应用程序中,执行继续任务时,主线程上的SynchronizationContext.Current为null.
private void button2_Click(object sender, EventArgs e)
{
if (SynchronizationContext.Current == null)
{
Debug.Fail("SynchronizationContext.Current is null");
}
Task.Factory.StartNew(() =>
{
CallWCFWebServiceThatThrowsAnException();
})
.ContinueWith((t) =>
{
//update the UI
UpdateGUI(t.Exception);
if (SynchronizationContext.Current == null)
{
Debug.Fail("SynchronizationContext.Current is null");
}
}, CancellationToken.None,
TaskContinuationOptions.OnlyOnFaulted,
TaskScheduler.FromCurrentSynchronizationContext());
}
Run Code Online (Sandbox Code Playgroud)
什么可能导致主线程的SynchronizationContext.Current变为null?
编辑:
@Hans要求堆栈跟踪.这里是:
at MyApp.Framework.UI.Commands.AsyncCommand.HandleTaskError(Task task) in d:\sources\s2\Framework\Sources\UI\Commands\AsyncCommand.cs:line 157 at System.Threading.Tasks.Task.c__DisplayClassb.b__a(Object obj) at System.Threading.Tasks.Task.InnerInvoke() at System.Threading.Tasks.Task.Execute() at System.Threading.Tasks.Task.ExecutionContextCallback(Object obj) at System.Threading.ExecutionContext.runTryCode(Object userData) at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, …
我不完全清楚应用程序中有多少Dispatchers以及它们与Threads相关或引用的方式.
据我所知,WPF应用程序有2个线程(一个用于输入,另一个用于UI)和1个调度程序(与UI-Thread相关联).如果我创建另一个线程 - 让我们称之为"工作线程" - 当我调用Dispatcher.CurrentDispatcher工作线程时,我会得到哪个调度程序怎么办?
另一种情况:假设一个带有2个线程的控制台应用程序 - 主线程和输入线程.在主线程上,我首先创建输入线程,然后我调用Application.Run()
Thread thread = new Thread(new ThreadStart(UserInputThreadFunction));
thread.Start();
Application.Run();
Run Code Online (Sandbox Code Playgroud)
会有一个调度员,对吗?在输入线程上,Dispatcher.CurrentDispatcher是否返回主线程的调度程序?或者将实例提供给主线程调度程序的正确方法是什么?
可能是WPF应用程序中有多个调度程序吗?有没有,创建另一个调度员是有意义的吗?
我们正在开发一个WPF应用程序,它将同时打开许多报告(就像典型的MDI应用程序,如Excel或Visual Studio).虽然可以让这些报告的数据上下文在多个工作线程中运行,但我们仍然发现,如果打开的报告数量非常大,甚至是这些报告的呈现(基本上是在MDI环境中托管的UserControl,或者只是在主视图中的网格区域仍然会使应用程序响应较慢.
所以,我的想法是至少在主UI中有几个区域,每个区域都有其用户控件在不同的UI线程中运行.再次,想象一下视觉工作室中的典型视图,除了菜单之外,它具有文本编辑器的主要区域,存在例如解决方案资源管理器的侧面区域,以及承载例如错误列表和输出的底部区域.所以我希望这三个区域在三个UI线程中运行(但自然它们托管在一个MainView中,这是我不确定的部分).
我问,因为我知道可以在不同的UI线程中运行几个(顶级)窗口.但是有人说它不适用于用户控件.这是真的吗?如果是这样,我的场景的典型解决方案是什么,即打开的UserControl的数量真的很大,而且这些UserControl中的许多都是实时的,因此渲染它们需要大量的资源?谢谢!
首先,我需要说我是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中刷新我的图像.
当我不将计算放在单独的线程中时,我可以刷新或构建我的图像.
首先,这是我的错误的错误日志条目
crash program @ 15-9-2011 15:01:30error:System.InvalidOperationException: Dispatcher processing has been suspended, but messages are still being processed.
at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
无论如何代码:
private void TB_postcode_cijfers_TextChanged(object sender, TextChangedEventArgs e){
if (TB_postcode_cijfers.Text != string.Empty || TB_postcode_cijfers.Text.Length > 0)
{
LBL_postcode.Content = Postcode_cijfers + Postcode_letters;
if (TB_postcode_cijfers.Text.Length == 4 && TB_postcode_letters.Text.Length == 2)
{
if (!ZoekOpPostcode(Injectioncheck(TB_postcode_cijfers.Text + TB_postcode_letters.Text)))
{
//MessageBox.Show("Geen resultaat gevonden, " + errortext);
if (MessageBox.Show("Geen resultaat gevonden, " + errortext + ".\n Wilt u …Run Code Online (Sandbox Code Playgroud) 我无法从流程内部收听自动化事件.我在下面写了一个示例,其中有一个带有单个按钮的简单WPF应用程序.使用TreeScope:Descendants在窗口上为Invoke事件添加自动化处理程序.
public MainWindow()
{
InitializeComponent();
Loaded += OnLoaded;
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
IntPtr windowHandle = new WindowInteropHelper(this).Handle;
Task.Run(() =>
{
var element = AutomationElement.FromHandle(windowHandle);
Automation.AddAutomationEventHandler(InvokePattern.InvokedEvent, element, TreeScope.Descendants,
(s, a) =>
{
Debug.WriteLine($"Invoked:{a.EventId.Id}");
});
});
}
private void button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Clicked!");
}
Run Code Online (Sandbox Code Playgroud)
当我点击按钮时,这就是我得到的:
Invoked:20009
Clicked!
Invoked:20009
Run Code Online (Sandbox Code Playgroud)
为什么Invoked事件被处理两次?
如果我删除Task.Run我只能得到它一次,但我已经阅读了几个你不应该从UI线程调用自动化代码的地方(例如https://msdn.microsoft.com/en-us/ library/ms788709(v = vs.110).aspx).在真实代码中这样做也是不切实际的.
我在此示例中使用了UIAComWrapper库,但是我对UIAutomationClient库的托管版和COM版都有相同的行为.