遗留库-在C#控制台应用程序中使用时存在线程问题,在Windows WPF应用程序中使用时没有问题

9rbhqvlz  于 2023-08-07  发布在  C#
关注(0)|答案(1)|浏览(93)

我正在与一个遗留库(我认为是用 Delphi 编写的,无法访问源代码)作斗争。它附带了一个C# Windows Forms演示应用程序,其中:
1.在主线程中执行遗留库的一些基本用法(获取版本等)
1.使用C# ThreadPool执行由用户输入触发的任何“真实的”使用。输出线程id表明所有相关场景都可以正常工作。
但是,当在控制台应用程序中复制此操作时,它就不起作用了。

  • 在主线程中顺序执行相关动作-> ok
  • 模仿演示应用程序,在主线程中进行简单的初始调用,在辅助线程中执行操作->通常不可以
  • 跳过主线程工作并在辅助线程中执行操作->通常只允许第一个线程执行工作。后续线程无法正确执行工作。

经过很多挠头,我决定创建一个超级简单的WPF应用程序,看看是否会有任何不同。嗯,它只是完美地工作。。我把修改过的代码放在了问题的最后。
鉴于WPF应用程序和经典的Windows窗体应用程序都可以正常工作,我的主要问题是:是什么原因导致Windows GUI应用程序和控制台应用程序之间在多线程库使用方面存在如此大的差异?澄清:在我的控制台应用程序中,我尝试了许多方法,ThreadPool,Thread objects,Tasks,...没有什么是可靠的。

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            string version = "";
            Legacy.GetVersion(ref version);
            this.status.Text = version;
        }

        void output(string output)
        {
            this.status.Dispatcher.Invoke( () => { this.status.Text += output; });
            
        }

        void connect(string ip, uint id)
        {
            var settings = new Settings();
            settings.IPAddress = ip;

            output($"thread {Environment.CurrentManagedThreadId} is connecting to device {id}");

            var result = Legacy.Connect(id, settings);
            output($"connect result for device {id} and thread {Environment.CurrentManagedThreadId}: " + Legacy.ResultString(result));
            if (Legacy.Ok((uint)result))
            {
                var info = new Info();
                result = Legacy.GetInfo(id, info);
                output(info.DeviceId);
            }

            result = Legacy.Disconnect(id);
            output("disconnect result: " + Legacy.ResultString(result));
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem((object bla) => connect("10.0.0.146", 1));
            
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem((object bla) => connect("10.0.0.139", 2));
        }
    }
}

字符串

deyfvvtc

deyfvvtc1#

马修给我指出了正确的方向。
最终的解决方案是,快速版本:

static void Main(string[] args)
        {

            var messagePumpThread = new Thread(() => {
                string version = "";
                // very first usage of Legacy should be in this thread
                // to make sure it registers this thread as its message pump thread
                Legacy.GetVersion(ref version);
                Console.WriteLine($"thread {Environment.CurrentManagedThreadId} version {version}");
                Application.Run();

            });
            messagePumpThread.Start();

            // sync to make sure the message pump started correctly
            // make multi threaded use of Legacy library

        }

字符串

相关问题