【问题标题】:CefSharp's Minimal Example and Multi-ThreadingCefSharp 的最小示例和多线程
【发布时间】:2015-02-23 12:26:37
【问题描述】:

我尝试在我的应用程序中实现最小示例。在这个应用程序中,我通过以下方式调用 Marketing-Windows(即 ChromiumWebBrowser): 我的 App.xaml.cs 看起来是这样的:

namespace ASA_Videowand
{
    public partial class App
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            // ...
                foreach (List<string> myStrings in Screen.AllScreens.Select(myScreen => _xml.GetScreenConfigs(i)))
                {
                     // ...
                            int i1 = i;
                            List<string> strings = myStrings;
                            var newWindowThread = new Thread(() =>
                            {
                                var myMarketing = new Marketing(i1, strings[0]);
                                myMarketing.Show();
                                Dispatcher.Run();
                            });
                            newWindowThread.SetApartmentState(ApartmentState.STA);
                            newWindowThread.IsBackground = true;
                            newWindowThread.Start();
                        }
                        else
                        {
                            // ...
                        }
                    }
                    i++;
                }
            }
        }
    }
}

这是我的 Marketing.xaml 和 Marketing.xaml.cs:

<Window x:Class="ASA_Videowand.Marketing"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:main="clr-namespace:ASA_Videowand.Views"
        Title="{Binding WebBrowser.Title}">
    <Grid>
        <main:MainView />
    </Grid>
</Window>

namespace ASA_Videowand
{
    public partial class Marketing
    {
        public Marketing(int screenNumber, string myLink)
        {
            InitializeComponent();
        }
    }
}

我的 MainView.xaml 来了:

<UserControl x:Class="ASA_Videowand.Views.MainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
             mc:Ignorable="d"
             d:DesignWidth="640"
             d:DesignHeight="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <cefSharp:ChromiumWebBrowser Grid.Row="0"
                                     Address="http://www.google.com"
                                     WebBrowser="{Binding WebBrowser, Mode=OneWayToSource}"
                                     Title="{Binding Title, Mode=TwoWay}" />
        <StatusBar Grid.Row="1">
            <ProgressBar HorizontalAlignment="Right"
                         IsIndeterminate="{Binding WebBrowser.IsLoading}"
                         Width="100"
                         Height="16"
                         Margin="3" />
            <Separator />
            <!-- TODO: Could show hover link URL here -->
            <TextBlock />
        </StatusBar>
    </Grid>
</UserControl>

还有我的 MainView.xaml.cs:

namespace ASA_Videowand.Views
{
    public partial class MainView : UserControl
    {
        public MainView()
        {
            InitializeComponent();
            DataContext = new MainViewModel();
        }
    }
}

在它继续之前,它会在 MainView.xaml 中停止,并带有例外,即

<cefSharp:ChromiumWebBrowser Grid.Row="0"
                                     Address="http://www.google.com"
                                     WebBrowser="{Binding WebBrowser, Mode=OneWayToSource}"
                                     Title="{Binding Title, Mode=TwoWay}" />

将属于另一个线程,因此无法修改。 我是多线程的新手。如果我尝试使用内置的 IE-WebControl,它可以正常工作。我知道如何从代码隐藏中调用某些内容,但是在视图中获取此异常对我来说是新的。 我怎样才能使这项工作?我很感激任何想法。谢谢。

【问题讨论】:

  • 你能把确切的错误也写出来吗?
  • 我怎样才能完成这项工作?...简单...不要在后台线程上进行 UI 工作。
  • 在德语中:{"Der aufrufende Thread kann nicht auf dieses Objekt zugreifen, da sich das Objekt im Besitz eines anderen Threads befindet."} 英文翻译应该是这样的:“调用线程不能访问此对象,因为该对象由另一个线程拥有。”
  • 是的,但是线程错误是在创建窗口时引起的。我只想在他们自己的线程中调用窗口。但我该怎么做呢?从来没有同时使用过视图和多线程。
  • 看在上帝的份上,使用任务

标签: c# wpf multithreading xaml


【解决方案1】:

简单地说:

你不能在后台线程上做 UI 工作

只需使用 UI 线程来完成您的 UI 工作:

foreach (List<string> myStrings in Screen.AllScreens.Select(myScreen => _xml.GetScreenConfigs(i)))
{
     // ...
            int i1 = i;
            List<string> strings = myStrings;
            var myMarketing = new Marketing(i1, strings[0]);
            myMarketing.Show();
        }
        else
        {
            // ...
        }
    }
    i++;
}

【讨论】:

  • 当我调用这个窗口 12 次(是的,它在一个总共有 16 个屏幕的服务器上运行),并通过 XAML 在每个窗口中启动一个 ChromiumWebBrowser,所有 12 个在一个线程中运行并且服务器关闭到他的膝盖上。我需要在不同的线程中运行 WebBrowsers。所以你说,我不能使用 XAML 来初始化它们?这将很难转移到我的应用程序中。有趣的是,当我使用这种任务时,不使用视图,而是一个简单的 WebBrowser(基于 IE 的),一切正常。
  • 我不是说你不能使用 XAML,我是说你不能在后台线程上运行 UI 代码。如果您的控件没有与 UI 相关的代码,那么您可以在后台线程上运行它,但必须有一个比运行十几个您不想在用户界面。