当用户点击按钮时,我想停止在main()中启动的调度程序.
private void button_start_Click(object sender, RoutedEventArgs e)
{
...
Camera.EventFrame -= onFrameEventFocusCam; //unsubscribe event
while (!Dispatcher.HasShutdownStarted)
{
// test if Dispatcher started shutdown --> ok, it does but never finishs...!
}
...
}
private void onFrameEventFocusCam(object sender, EventArgs e)
{
...
Dispatcher.Invoke(new Action(() =>
{
// Convert bitmap to WPF-Image
var bmp = new Bitmap(bitmap);
var hBitmap = bmp.GetHbitmap();
System.Windows.Media.ImageSource wpfBitmap = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
image_fokus.Source = wpfBitmap;
image_fokus.Stretch = System.Windows.Media.Stretch.UniformToFill;
DeleteObject(hBitmap);
bitmap.Dispose();
}));
GC.Collect();
}
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,我在以下位置停止时收到以下错误消息onFrameEventFocusCam …
我需要编写一个围绕第三方api的包装器,它会使用消息泵,因此根据是否在UI线程(例如在wpf应用程序中)实例化包装器(例如控制台应用程序),需要对其进行非常不同的处理).
如果它不在UI线程上运行,那么我需要一个调度程序并实现我自己的消息泵.
为此,我需要知道包装器是否在wpf应用程序中实例化.仅确定实例化是否发生在UI线程上是不够的(即使在wpf应用程序中,实例化包装器的线程可能不是UI线程).
有什么办法我可以弄清楚我是在一个带有消息泵或控制台应用程序的wpf或windows窗体环境中我必须实现自己的消息泵吗?
谢谢
当你有一个按钮,并执行以下操作:
Private Function Button_OnClick
Button.Enabled = False
[LONG OPERATION]
End Function
Run Code Online (Sandbox Code Playgroud)
然后该按钮不会变灰,因为长操作会阻止UI线程重新绘制控件.我知道正确的设计是启动后台线程/调度程序,但有时这对于简单的操作来说太麻烦了.
那么如何强制按钮在禁用状态下重绘?我在Button上尝试了.UpdateLayout(),但它没有任何效果.我也尝试过使用WinForms时通常可以正常工作的System.Windows.Forms.DoEvents(),但它也没有效果.
我们有一个用C++编写的自制COM组件.我们现在想在C#测试项目中测试它的功能和事件.功能测试非常简单.但是,事件永远不会被触发.
MyLib.MyClass m = new MyLib.MyClass();
Assert.IsTrue(m.doStuff()); // Works
// This does not work. OnMyEvent is never called!
m.MyEvent += new MyLib.IMyClassEvents_MyEventHandler(OnMyEvent);
m.triggerEvent();
Run Code Online (Sandbox Code Playgroud)
我已经在Google上搜索了这个并在StackOverflow上阅读了类似的问题.我已经尝试了所有提出的方法,但无法使其正常工作!
到目前为止,我已经尝试使用主动调度员运行我的测试,但没有成功.我也尝试使用在主线程中手动泵送消息Dispatcher.PushFrame().没有.我的事件永远不会触发 我创建了一个简单的WinForms项目并验证我的事件在正常设置中工作.因此,此问题仅适用于单元测试.
问:如何进行可以成功触发活动事件处理程序的常规C#单元测试?
那里的人应该有一份工作样本!请帮忙.
我试图遵循在单元测试中使用WPF Dispatcher的建议,以便运行我的nUnit测试.
当我按如下所示编写单元测试时,它可以工作:
[Test]
public void Data_Should_Contain_Items()
{
DispatcherFrame frame = new DispatcherFrame();
PropertyChangedEventHandler waitForModelHandler = delegate(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "Data")
{
frame.Continue = false;
}
};
_myViewModel.PropertyChanged += waitForModelHandler;
Dispatcher.PushFrame(frame);
Assert.IsTrue(_myViewModel.Data.Count > 0, "Data item counts do not match");
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我尝试使用DispatcherUtil的建议,它不起作用:
[Test]
public void Data_Should_Contain_Items()
{
DispatcherUtil.DoEvents();
Assert.IsTrue(_myViewModel.Data.Count > 0, "Data item counts do not match");
}
public static class DispatcherUtil
{
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public static void DoEvents()
{ …Run Code Online (Sandbox Code Playgroud) 我有一个带有进度条的C#Windows窗体应用程序.我想根据某些方法状态动态地进行.我在一个单独的类中有该方法,并为该方法创建一个新线程,并使用委托将该方法的状态传递给父线程.
我可以在WPF应用程序中解决相同的情况progressbar.Dispatcher但在Windows窗体应用程序中没有Dispatcher,即使我使用System.Threading命名空间.
progressbar.Dispatcher 似乎只在WPF应用程序中可用.
由于多租户情况下的特定项目,我设置了一个具有相当深的统计文件级别的调度程序.
我希望能够以递归方式刷新目录以模仿其他租户更浅的统计文件级别.
是否有调度程序刷新命令允许我显式删除内容目录?
我在WPF应用程序中有一些代码如下所示:
public class MyTextBox : System.Windows.Controls.TextBox, IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
Dispatcher.BeginInvoke((Action) delegate
{
// do work on member variables on the UI thread.
});
}
~MyTextBox()
{
Dispose(false);
}
}
Run Code Online (Sandbox Code Playgroud)
dispose方法永远不会被显式调用,因此析构函数会调用它.看起来在这种情况下,对象将在BeginInvoke中的委托在UI线程上触发之前被销毁.它似乎工作了.这里发生了什么?这样安全吗?
这是MSDN提供的代码,虽然它似乎不清楚它在做什么:
[SecurityPermissionAttribute(SecurityAction.Demand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public void DoEvents()
{
DispatcherFrame frame = new DispatcherFrame();
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background,
new DispatcherOperationCallback(ExitFrame), frame);
Dispatcher.PushFrame(frame);
}
public object ExitFrame(object f)
{
((DispatcherFrame)f).Continue = false;
return null;
}
Run Code Online (Sandbox Code Playgroud)
我刚刚注意到今天在DoEvents定义该方法的一些遗留代码中的类似实现。为什么我们需要这个以及将框架推送到调度程序上意味着什么?
我有一个WPF(使用.net 4.5和mvvmlight)的启动画面,它必须以异步方式执行各种加载操作,显示进度并偶尔要求用户输入.
当要求输入,我将创建表单/对话框关闭UI线程调用的ShowDialog(与闪屏作为父),这样不会出现跨线程问题.这一切都很好但是如果在请求输入时发生错误,则导致的异常丢失.
为简单起见,下面的示例根本不遵循MVVM.
这是我的app.cs,它设置了UI调度程序,并准备处理错误报告的任何未处理的调度程序异常:
public partial class App : Application
{
private void Application_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
System.Windows.Forms.MessageBox.Show("Exception Handled");
}
private void Application_Startup(object sender, StartupEventArgs e)
{
GalaSoft.MvvmLight.Threading.DispatcherHelper.Initialize();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的(非常简化的)启动/启动屏幕:
private void Window_ContentRendered(object sender, EventArgs e)
{
System.Windows.Forms.MessageBox.Show("Starting long running process...");
var t = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
//some kind of threaded work which decided to ask for user input.
GalaSoft.MvvmLight.Threading.DispatcherHelper.UIDispatcher.Invoke(() =>
{
//Show form for user input, launched on UIDispatcher so that it's created …Run Code Online (Sandbox Code Playgroud) dispatcher ×10
c# ×8
wpf ×7
ui-thread ×2
unit-testing ×2
.net ×1
aem ×1
com ×1
mvvm-light ×1
nunit ×1