簡體   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