繁体   English   中英

C#线程化FolderBrowserDialog

[英]C# threading a FolderBrowserDialog

我正在尝试使用FolderBrowserDialog在C#中选择一个文件夹。 起初我有一个Thread异常,所以我用Google搜索出了什么问题并解决了这个问题,但现在陷入了另一个问题。 我想知道何时选择了一个文件夹。

这就是我现在得到的。

 private void btnWorkingFolder_Click(object sender, EventArgs e)
    {


        var t = new Thread(SelectFolder);
        t.IsBackground = true;
        t.SetApartmentState(ApartmentState.STA);
        t.Start();

    }

    private void SelectFolder()
    {
        FolderBrowserDialog dialog = new FolderBrowserDialog();
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            txtWorkFolder.Text = dialog.SelectedPath;
        }
    }
}

这里的问题是我不能为txtWorkingFolder设置文本,因为我不在同一线程中。 我不想更改txtWorkingFolder的线程,所以我的问题是,一旦设置了DialogResult.OK,如何从新线程更改其值?

编辑:

这是主要的,btnWorkingFolder是Form1()的一部分:

class sample
{

    static void Main(string[] args)
    {

       Connect2Exchange conn = new Connect2Exchange();

       Application.EnableVisualStyles();
       Application.SetCompatibleTextRenderingDefault(false);

       Application.Run(new Form1());       

    }


}

第二编辑:

从给出的示例尝试代码后,发生以下异常:

System.Threading.ThreadStateException was unhandled
  Message=Current thread must be set to single thread apartment (STA) mode before OLE calls can be made. Ensure that your Main function has STAThreadAttribute marked on it. This exception is only raised if a debugger is attached to the process.
  Source=System.Windows.Forms
  StackTrace:
       at System.Windows.Forms.FolderBrowserDialog.RunDialog(IntPtr hWndOwner)
       at System.Windows.Forms.CommonDialog.ShowDialog(IWin32Window owner)
       at System.Windows.Forms.CommonDialog.ShowDialog()
       at Mail2DB.Form1.btnWorkingFolder_Click(Object sender, EventArgs e) in C:\Users\marthin\documents\visual studio 2010\Projects\Mail2DB\Mail2DB\Form1.cs:line 44
       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(Int32 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 Mail2DB.sample.Main(String[] args) in C:\Users\marthin\documents\visual studio 2010\Projects\Mail2DB\Mail2DB\sample.cs:line 26
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 

感谢您的帮助! /马丁

您应该使用Invoke将执行委派给GUI线程:

private void SelectFolder()
{
    FolderBrowserDialog dialog = new FolderBrowserDialog();
    if (dialog.ShowDialog() == DialogResult.OK)
    {
        Action a = () => txtWorkFolder.Text = dialog.SelectedPath;
        this.Invoke(a);
    }
}

同样也不清楚您要在这里实现什么。 使用后台线程创建文件浏览器对话框没有任何意义。 该任务可以并且应该很好地在主线程上执行。

后台线程用于执行与UI无关的可能长时间运行的任务,以避免阻塞主线程。

这里使用线程非常不合适。 该对话框已经能够在UI线程上运行,而不会干扰其余窗口的更新。

STA和更新文本框的麻烦只是其中的一小部分。 还有一个更大的问题,该对话框没有父窗口。 线程上没有其他窗口可以用作父窗口,只有桌面窗口是候选窗口。 当用户激活另一个窗口时,故障开始。 它可能与对话框重叠,并且用户没有很好的方法来返回它。 没有任务栏按钮。 这也可能是由于在错误的时间闲置点击而偶然发生的。 用户甚至可能从未看到该对话框,而没有意识到该对话框实际上是在显示。

另一个问题是该对话框不会对您的其余窗口产生模态。 它们保持启用状态,允许用户操作用户界面并再次启动对话框。

只是使它像这样工作:

private void btnWorkingFolder_Click(object sender, EventArgs e)
{
    using (var dialog = new FolderBrowserDialog()) {
        if (dialog.ShowDialog() == DialogResult.OK)
        {
            txtWorkFolder.Text = dialog.SelectedPath;
        }
    }
}

如果确实需要对话框独立于其余窗口运行,则需要提供一个可以充当父窗口的“宿主”窗口。 现在,这还要求您使用Application.Run()泵送消息循环。 针对使用户再次弹出对话框的对策,使用Enabled属性。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM