如何为DLL内部的WPF表单创建单独的STA线程,而不是WPF应用程序?

时间:2014-06-26 00:39:33

标签: c# .net wpf sta

我有一个包含WPF表单的dll。这个DLL将由另一个WPF应用程序调用,不幸的是我无法触摸它。问题是我的WPF表单中没有Main方法来放置

[STAThread]
static void Main() {
    //...
}

异常会在我的类的构造函数上抛出。在这种情况下,如何解决此STA问题。同样,这不是一个WPF应用程序,而是一个位于dll内部的WPF表单。

namespace VisualScannerTest
{
    /// <summary>
    /// Interaction logic for VisualScanner.xaml
    /// </summary>
    public partial class VisualScanner :Window,IPeripheral<VisualScanner.VisualScannerSettings>
    {
        private VisualScannerSettings _settings;
        private readonly IEventManager _eventManager;


        public VisualScanner(IEventManager eventManager):base()
        {
            InitializeComponent();
            _eventManager = eventManager;
        }


        private void SubmitButton_Click(object sender, RoutedEventArgs e)
        {
             string input = InpuTextBox.Text;
             InpuTextBox.Text = string.Empty;
            if (!string.IsNullOrWhiteSpace(input))
            {
                _eventManager.GetEvent<PeripheralEvent>().Publish(new PeripheralEventData {RawData = input});
            }

        }


        public void Initialize(VisualScannerSettings settings)
        {
            _settings = settings;
        }

        public IEnumerable<string> RegisterImpulses()
        {
            yield break;
        }

        public string Type
        {
            get { return GetType().FullName; }
        }
         public sealed class VisualScannerSettings:PeripheralSettings
        {
            public string Data { get; set; }   
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我会建议您将dll转换为另一个拥有它自己的线程的WPF应用程序,然后您需要一种不同的方式与它进行通信 - 例如使用另一个dll两个应用程序引用或使用{{{{ 3}},例如TCP套接字。

或者,您可以尝试在dll中公开需要在消费者的STA线程上调用的内容。所以你的应用程序可以调用它,例如:

CreateForm();
例如,

虽然这可能不起作用 - 你需要设置一些东西来使WPF打勾,这不仅仅是使用STA线程的问题:

  1. 将SetSynchronizationContext设置为DispatcherSynchronizationContext

    SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));

  2. 创建System.Windows.Application()

  3. 使用Application.LoadComponent()`加载和添加任何XAML资源。

    var resources = System.Windows.Application.LoadComponent(new Uri(&#34; /Styles.xaml",UriKind.Relative)); Resources.MergedDictionaries.Add(资源);

  4. 您需要以编程方式抽取Dispatcher

    Dispatcher.CurrentDispatcher.PushFrame();

答案 1 :(得分:1)

我有同样的问题。您需要使用TaskScheduler。重要的是设置ApartmentState。

public static async Task Main()
{
  var taskScheduler = new SingleThreadTaskScheduler(ApartmentState.STA);
  var taskList = new List<Task>();

  var updateTask = Task.Run(InstallHelper.CheckForUpdatesAsync);
  updateTask.Wait();
  taskList.Add(updateTask);
  var tasks = await Task.Factory.ContinueWhenAll(taskList.ToArray(), result => 
                    Task.Factory.StartNew( ()=>MyAppSynchronMethodToRunIn_STAThread, 
                    taskScheduler));
}