如何解决CommonOpenFileDialog-从UI线程调用后,跨线程操作无效
所以我正在使用WindowsAPICodepack中的CommonopenFileDialog。在我正在编写的应用程序的早期版本中,CommonopenFileDialog可以正常工作。在针对更高版本的.Net Framework的当前版本中,即使对话框是通过主窗体中的toolstripMenuItem click事件从主UI线程调用的,我也会得到跨线程操作无效的异常。以前曾经通过主窗体的按钮clickhandler以类似的方式调用它。
显式调用以相同形式显示CommonopenFileDialog的相同代码即可解决此问题,但通常的对话框行为会丢失。
这行得通,但是没有this。调用它不行。
private void loadWorkspacetoolStripMenuItem_Click(object sender,EventArgs e)
{
bool wait = true;
this.Invoke((MethodInvoker)delegate ()
{
string startPath = LastUsedpath;
if (FileFolderTools.ShowFolderChooser(ref startPath))
{
workspace.LoadWorkspace(startPath);
LastUsedpath = startPath;
}
wait = false;
});
while(wait){}
}
此外,尽管while(wait)在那里,但UI仍然是响应的,而通常情况下,按下按钮进行阻塞调用时情况并非如此。不知道这是怎么回事...
编辑:底部有更广泛的堆栈跟踪。
编辑-这是ShowfolderChooser所做的(确定时返回true,取消时返回false):
public static bool ShowFolderChooser(ref string path){
CommonopenFileDialog dialog = new CommonopenFileDialog();
dialog.InitialDirectory = path;
dialog.IsFolderPicker = true;
CommonFileDialogResult res = dialog.ShowDialog();
if (res == CommonFileDialogResult.Ok)
{
path = dialog.FileName; //set new path on OK
return true;
}
return false;
}
完全例外:
This exception was originally thrown at this call stack:
[External Code]
DataManagement.DataManagementCore.Helpers.FileFolderTools.ShowFolderChooser(ref string) in FileFolderTools.cs
Camera._Camera.btn_exportAll_Click(object,System.EventArgs) in Camera.cs
[External Code]
Camera.Program.Main() in Program.cs
但是等等...!还有更多...
因此,我尝试将这些代码放在单独的应用程序中,并且可以正常工作。所以我想这与我的应用程序有关。我看到的一个很大的区别是,我在loadWorkspacetoolStripMenuItem_Click
上的Stack框架有一个堆栈条目user32.dll![Frames...
,知道这个来自哪里吗?我认为这与此有关...
EDIT2 :更广泛的堆栈跟踪:
at System.Windows.Forms.Control.get_Handle()
at Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialog.ApplyNativeSettings(IFileDialog dialog)
at Microsoft.WindowsAPICodePack.Dialogs.CommonFileDialog.ShowDialog()
at Camera._Camera.btn_exportAll_Click(Object sender,EventArgs e) in D:\XXXXXXXXXXXXXX\TestProjects\DataManagementTestProject\Camera\Mainscreen\Camera.cs:line 661
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnClick(EventArgs e)
at System.Windows.Forms.Button.onmouseup(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m,MouseButtons button,Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.dispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.imsoComponentManager.FPushMessageLoop(IntPtr dwComponentID,Int32 reason,Int32 pvLoopData)
at System.Windows.Forms.Application.threadcontext.RunMessageLoopInner(Int32 reason,ApplicationContext context)
at System.Windows.Forms.Application.threadcontext.RunMessageLoop(Int32 reason,ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at DataManagementTestProject.Program.Main() in D:\XXXXXXXXXXXXXX\TestProjects\DataManagementTestProject\Program.cs:line 20
从此堆栈跟踪中,我可以确认调用是在UI的主线程上完成的,因为它由MessageLoop正确地调用了。似乎getHandle存在问题,某处出错。但这在API包中应该可以使用...
解决方法
因此,经过几个小时的工作,并仔细研究了github上的软件包问题,我找到了答案here。
尽管问题不同,但原因是相同的:获取窗口句柄时出现问题。通过使用指定的当前表单的句柄调用对话框,在获取句柄时不再有跨线程访问。
最终解决方案:向函数调用添加一个指针。并将表单的句柄传递给对话框。
string path = LastUsedPath;
if (FileFolderTools.ShowFolderChooser(ref path,this.Handle)){
workspace.LoadWorkspace(path);
LastUsedPath = path;
}
public static bool ShowFolderChooser(ref string path,IntPtr handle)
{
CommonOpenFileDialog dialog = new CommonOpenFileDialog();
dialog.InitialDirectory = path;
dialog.IsFolderPicker = true;
CommonFileDialogResult res = dialog.ShowDialog(handle);
if (res == CommonFileDialogResult.Ok)
{
path = dialog.FileName; //set new path on OK
return true;
}
return false;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。