【问题标题】:Target UI Thread Control for threadsafe calls用于线程安全调用的目标 UI 线程控制
【发布时间】:2011-12-01 07:09:43
【问题描述】:

我正在研究线程安全调用,这非常困难。我有一种方法可以帮助我将新选项卡添加到选项卡控件,但我想从 UI 不关联的线程调用它。

我当前的标签创建代码如下所示。它不是线程安全的。

 TabPage tpage = new TabPage();
 tpage.BorderStyle = System.Windows.Forms.BorderStyle.None;

 //tabcontrol_borwser is the name of the tabcontrol on my ui
 tabcontrol_browser.TabPages.Insert(tabcontrol_browser.TabCount, tpage);

我将如何从一个单独的线程执行此操作,该线程允许我按主 UI 线程上存在的名称定位相同的控件?

我不想为每个控件创建线程安全的包装类,因为我必须为我创建的每个 UI 控件执行此操作,真是麻烦!

最简单的逻辑方法是创建一个像这样工作的名称持有者:

PrimaryThread.Control.tabcontrol_browser.TabPages.Insert(tabcontrol_browser.TabCount, tpage);

有没有办法让我这样做?

这是用于创建标签的整个方法:

    private String f_create_new_tab(string tab_name)
    {
        // create a new TabPage object
        tabcontrol_browser.Invoke( () => {
            TabPage tpage = new TabPage();
            tpage.BorderStyle = System.Windows.Forms.BorderStyle.None;


            //add the newly created TabPage
            //to the tabcontrol's collection of tab pages 
            tabcontrol_browser.TabPages.Insert(tabcontrol_browser.TabCount, tpage);
            int count = tabcontrol_browser.TabCount;
            tab_name = count.ToString() + ") " +tab_name;
            tpage.Text = tab_name;
            tpage.Name = tab_name;

            //create a WebBrowser object
            WebBrowser browser = new WebBrowser();
            browser.Name = "browser_" + tab_name;
            browser.Navigate("http://www.google.com");
            WaitBrowserLoading();
            //add the browser object to the tab page 
            //you created previously
            tpage.Controls.Add(browser);
            browser.Dock = DockStyle.Fill;
            tabcontrol_browser.SelectTab(tpage);

            //add some event handlers to your browser object
            browser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(f_browser_pagechange);
            string browsername = "browser_" + tab_name;
            return browsername;
        });
    }

【问题讨论】:

  • 如果你必须使其线程安全,你必须从你使用的任何地方序列化对 tabcontrol_browser 的访问,或者你只想线程安全 tabcontrol_browser.TabPages.Insert() 调用?
  • 我可以通过序列化访问来分配/同步线程使用我的主线程 UI 的权限吗?
  • 只有 UI 线程可以处理控件。因此,如果您在 tabcontrol_browser 上调用 Insert 方法,如果当前线程不是您的主线程,则必须调用 Invoke。我还是不明白你真正想要什么,你想序列化访问 tabcontrol_browser 函数或其他东西。

标签: c# winforms multithreading


【解决方案1】:

不确定这是否会对您有所帮助,但每当我尝试回调 UI 线程以向 UI 发布内容或执行任何操作时,我都会使用此扩展方法:

   public static class ControlExtensions
   {
      public static void Invoke(this Control Control, Action Action)
      {
         Control.Invoke(Action);
      }
   }

这将是您的案例的用途:

   if(tabcontrol_browser.InvokeRequired())
   {     
      tabcontrol.Invoke( () => {
                                 TabPage tpage = new TabPage();
                                 tpage.BorderStyle = System.Windows.Forms.BorderStyle.None;
                                 tabcontrol_browser.TabPages.Insert(tabcontrol_browser.TabCount, tpage)
                               });
   }

【讨论】:

  • 我已经更新了我的问题以显示整个方法。但是我在 Invoke 行上遇到了这个错误。 ""无法将 lambda 表达式转换为类型 'System.Delegate',因为它不是委托类型""
猜你喜欢
  • 2017-04-21
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-30
相关资源
最近更新 更多