【问题标题】:Wpf multithreadingWpf 多线程
【发布时间】:2016-06-21 05:52:26
【问题描述】:
UserControls.userGridGunler ug = new UserControls.userGridGunler();//My user control
ug.Basliklar.ItemsSource = basliklar;
ug.Saatler.ItemsSource = saha.Satirlar;

TabItem ti = new TabItem();
ti.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate
{
    ti.Header = saha.SahaAdı + " (" + saha.SahaTipi + ")";
    ti.Content = ug;
});

//tabSahalar is my TabControl in mainWindow

tabSahalar.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate
{
    tabSahalar.Items.Add(ti);//PROBLEM IS HERE
    //tabSahalar.Items.Add(new TabItem { Header = "asdasdad" });//Problem no here
});

这是我的代码。我想多线程在 tabControl 中添加 tabitem。但我得到“调用线程无法访问此对象,因为另一个线程拥有它。”在“问题在这里”的地方出现错误。

我的另一个问题:

【问题讨论】:

  • 您的问题是非常常见的 UI 在一个线程上,而您无法从另一个线程使用它 - 请 google,并查看堆栈溢出,这有很多
  • 查看侧边栏,标题为“相关”,那里已经列出了几个有趣的答案 - 我们可能会以 stackoverflow.com/questions/1792129/… 的欺骗来结束这个问题?
  • 在 Invoke 操作中创建 TabItem (ti = new TabItem();)。
  • @CaKaL 你能通过电子邮件把你的解决方案发给我吗?
  • @EngineerSpock 为什么不呢?您的电子邮件地址?

标签: c# wpf multithreading async-await ui-thread


【解决方案1】:

您的名为 tiTabItem 不是在 UI 线程上创建的。 你应该在 UI 线程上创建它,所以你可以像这样包装它:

TabItem ti = null;
Application.Current.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, (Action)delegate
 {
   ti = new TabItem();
   ti.Header = saha.SahaAdı + " (" + saha.SahaTipi + ")";
   ti.Content = ug;
  });

【讨论】:

  • 此代码出现“对象引用未设置为对象实例”错误。因为 ti=null 还没有。
  • @CaKaL 对不起,应该有 Application.Current.Dispatcher.Invoke()。复制并重试。
  • 我尝试了这段代码,但我得到“必须在与 DependencyObject 相同的线程上创建 DependencySource”错误。 :(
  • @CaKaL 这是另一个问题,虽然类似。 basliklar 或 saha 不是在 UI 线程上创建的。您应该使用相同的技术在 UI 线程上创建它们 - 使用 Application.Current.Dispatcher。题目的问题就解决了。如果不难,请将其中一个答案标记为答案。我会尝试在 cmets 中帮助您,或者您可以创建另一个问题。
【解决方案2】:

WPF 应用程序中与您的任务相关的多线程功能的简单(但不一定是最佳)实现如下所示:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        // this simulates some User event, e.g. Button click
        AddMyTabItem();
    }

    // in real-life app this could be replaced w/event handler
    private async void AddMyTabItem()
    {
        try
        {
            TabItem ti = new TabItem();
            ti.Header = "MyTableItemHeader";
            ti.Content = "MyTableItemContent";
            await AddTabItem(ti);
        }
        catch { }
    }

    // implements async/await asynchronous for responsive UI
    private async Task AddTabItem(TabItem TI)
    {
        try
        {
            await TabControl1.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate
            {
                TabControl1.Items.Add(TI);
            });
        }
        catch { throw; }
     }
}

假设您在 XAML 中放置了 TabControl1,此代码将使用 asyncawait 编码技术在异步模式下动态添加另一个 TabItem ti 并设置其标题/内容属性。在现实生活中的应用程序中,它可能应该封装在 Button.Click 事件处理程序或类似的东西中(作为一般规则,async void 主要推荐用于 UI event 处理)。

希望这会有所帮助。

【讨论】:

    【解决方案3】:

    @EngineerSpock 通过电子邮件解决了我的问题。

    问题出在我的用户控件中,即 durumButon。

    新代码:

    public DURUM Durum
        {
            get
            {
                return _durum;
            }
    
            set
            {
                _durum = value;
    
                Application.Current.Dispatcher.Invoke(new Action(() =>
                {
    
                    if (value == DURUM.DOLU)
                    {
                        BGrenk = (SolidColorBrush)(new BrushConverter()).ConvertFromString("#FF740000");
                        IptalEtMenuItem = Visibility.Visible;
                        OdemeAlMenuItem = Visibility.Collapsed;
                        DetayMenuItem = Visibility.Visible;
                    }
                    else if (value == DURUM.KOMBİNE)
                    {
                        BGrenk = (SolidColorBrush)(new BrushConverter()).ConvertFromString("#FF740000");
                        IptalEtMenuItem = Visibility.Collapsed;
                        OdemeAlMenuItem = Visibility.Visible;
                        DetayMenuItem = Visibility.Visible;
    
                    }
                    else if (value == DURUM.REZERVE)
                    {
                        BGrenk = (SolidColorBrush)(new BrushConverter()).ConvertFromString("#00a8e6");
                        IptalEtMenuItem = Visibility.Visible;
                        OdemeAlMenuItem = Visibility.Visible;
                        DetayMenuItem = Visibility.Visible;
                    }
                    else if (value == DURUM.KAPORA)
                    {
                        BGrenk = (SolidColorBrush)(new BrushConverter()).ConvertFromString("#ffd800");
                        IptalEtMenuItem = Visibility.Visible;
                        OdemeAlMenuItem = Visibility.Visible;
                        DetayMenuItem = Visibility.Visible;
                    }
                    else if (value == DURUM.BOŞ)
                    {
                        BGrenk = (SolidColorBrush)(new BrushConverter()).ConvertFromString("#FF00AE18");
                        IptalEtMenuItem = Visibility.Collapsed;
                        OdemeAlMenuItem = Visibility.Visible;
                        DetayMenuItem = Visibility.Collapsed;
                    }
    
                    OnPropertyChanged("DURUM");
                }));
            }
        }
    

    我添加了 Application.Current.Dispatcher.Invoke(new Action(() =>{})); 代码块,我的问题已经解决了。

    【讨论】:

      猜你喜欢
      • 2013-01-16
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多