【问题标题】:Wrapping 3rd party lib for safe threading in WPF application包装 3rd 方库以在 WPF 应用程序中进行安全线程
【发布时间】:2022-01-25 10:43:21
【问题描述】:

我有一个需要在 WPF 应用程序中执行的第三方库。我知道下面的代码不会以 WPF 开头。可能值得记住,只是尝试将问题分解为一个较小的案例。

无论如何,他们没有太多的文档,或者我可以做的关于 3rd 方库,比它需要使用的要多。

因为有些任务在处理和时间方面相当长,所以我认为将这些任务放在单独的线程上管理以避免锁定 UI 是个好主意。 所以我的想法是让大部分工作可以在单独的处理线程中完成,并在安全的主 UI 线程上调用第 3 方库,然后将数据返回到线程以进行进一步处理。这是因为那里使用的代码可能不是完全线程安全的,无法从任何地方调用,到目前为止,这完全不走运。

所以我目前对此的想法是将需要的内容从 3rd 方库线程/任务分派到注册为主 UI 线程的内容,并收集数据并将其返回给处理线程。

预处理 -> 3pl -> 后处理。

这目前还没有完全起作用,因为没有例外或信息说明为什么它不起作用。因为它只是在ThirdPartyTest() 中运行InvokeOnMainTread 时死亡。

这里缺少什么才能让这个调用正常传递?

任何想法或帮助将不胜感激。

using System;
using System.Threading.Tasks;
using System.Windows.Threading;

namespace TestTPL
{
    class Program
    {      
        static void Main(string[] args)
        {
            ThreadMethods methods = new ThreadMethods();
            methods.Execute();
        }
    }

    public class ThreadMethods
    {
        private static ThirdPartyCaller caller;
        public async void Execute()
        {
            //Doing some pre processing...

            //Reach for 3rd party lib
            caller = new ThirdPartyCaller();
            int taskRes = await TestTask();

            //Do some more processing of data
            
        }

        private async Task<int> TestTask()
        {
            return await Task.Run(() =>
            {
                int project = caller.ThirdPartyTest();
                return project;
            });
        }
    }

    public class ThirdPartyCaller
    {
        private readonly Dispatcher dispatcher;

        public ThirdPartyCaller()
        {
            dispatcher = Dispatcher.CurrentDispatcher;
        }

        protected TResult InvokeOnMainTread<TResult>(Func<TResult> action)
        {
            return dispatcher.Invoke(action);
        }

        public int ThirdPartyTest()
        {
            return InvokeOnMainTread(() =>
            {
                //Represents calculations done by a third pary library
                return 2 + 6;
            });

       
        }
    }
}


【问题讨论】:

  • 能否补充更多关于第三方库API的信息?举一个类的例子,这个类的一些方法/属性,如果冻结不是问题,你将如何从 UI 线程使用这个类,可能会有帮助。
  • this 答案中你可以找到SingleThreadTaskScheduler 类,这可能会给你一些想法。

标签: c# wpf multithreading


【解决方案1】:

您的 Main 函数调用一个异步函数(执行),但不等待该调用完成。您要么需要将 .Wait() 添加到执行任务,要么等待它(但是旧版本的 C# 不允许您使 Main 异步)。目前,您的程序甚至在您的任务运行之前就退出了。

另外,主线程很可能被 Execute 函数中的await TestTask() 阻塞。因为您在 ThirdPartyCaller 构造函数在主线程上运行时设置 dispatcher,所以 Dispatcher.Invoke 可能永远不会执行委托,因为线程被阻塞等待 TestTask 完成。如果您想保留他“调用主”功能,您可能需要从 TestTask 中删除等待。

【讨论】:

  • 不确定通过传递 TResult 来完成代码是否足够。 VS告诉名称可以简化并且可以删除它。无论有没有它,它仍然无法通过代码的这一点。
  • 您正试图在主线程上调用该操作,但主线程被您的“await TestTask()”调用阻塞。您要么不需要等待该调用,要么需要在另一个线程上调用该操作。同一个线程不能同时等待您的 TestTask 并运行您的操作。
  • 我删除了两个“await”,只是让它在“while(true)”中运行,以免很快杀死它。代码永远不会从已调用的内容中找到返回值。
  • 只是好奇 - 你为什么首先尝试在主线程上调用第三方库?
  • methods.Execute() 也没有等待,但它是异步的。 Main 也可能会提前退出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-10
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多