C#WPF项目线程-需要帮助 [英] C# WPF Project Threading - Need Help

查看:41
本文介绍了C#WPF项目线程-需要帮助的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好.我是一个初学者程序员.我的大多数应用程序都非常简单,具有同步方法和操作.此外,其中许多都是控制台应用程序.

我现在已经阅读了好几篇文章,并尝试了一些东西,但是我似乎无法使它正常工作.

我有一个WPF窗口,许多以前的控制台应用程序现在都迁移到了这里.想法是让用户启动一个应用程序以执行所有操作,而不是启动5个不同的控制台应用程序.我想让用户在运行某个任务时可以在表单中执行其他任务,但是目前,它完全冻结了表单,并且被锁定,直到操作完成为止.

下面的内容接受来自文本框(服务器名称)的输入,然后停止并远程启动win2k8服务器上的某些服务.但是,此操作最多可能需要几分钟,并且表格被锁定直到完成.我需要一些帮助,使它在后台发生,并在执行按钮时禁用它.

Hello. I am a beginner programmer. Most of my applications have been pretty simple, with synchronous methods and operations. Also, many of them have been Console Apps.

I''ve read quite a few articles now, and have tried several things, but I just cannot seem to get this to work.

I have a WPF Window, with many different previously Console Apps now migrated to here. The idea is to have the users launch a single app to be able to perform all operations, rather than launching 5 different console apps. I''d like to enable to user to do other tasks inside the form when a certain task is running, but currently, it freezes the form entirely, and it is locked out until the operation is done.

The below accepts input from a textbox (server name), then stops and starts some services on a win2k8 server remotely. This operation, however, can take up to several minutes, and the form is locked out till done. I need some help on making this take place in the background, and disabling the button while it is executing.

private void btnCycleBankpro_Click(object sender, RoutedEventArgs e)
{
            string serverName = txtCycleBankProServer.Text.Trim().ToUpper();
            if (serverName != string.Empty)
            {
                CycleBankpro cycleBankpro = new CycleBankpro();
                Dispatcher.BeginInvoke(DispatcherPriority.Background, (ThreadStart)delegate
                {
                    txtCycleBankProOutput.Text += cycleBankpro.StopService("BPSCTL", serverName) + "\n";
                    txtCycleBankProOutput.Text += cycleBankpro.StopService("BPSNMSRV", serverName) + "\n";
                    txtCycleBankProOutput.Text += cycleBankpro.StopService("BPSLOG", serverName) + "\n\n";
                    txtCycleBankProOutput.Text += cycleBankpro.StartService("BPSNMSRV", serverName) + "\n";
                    txtCycleBankProOutput.Text += cycleBankpro.StartService("BPSLOG", serverName) + "\n";
                    txtCycleBankProOutput.Text += cycleBankpro.StartService("BPSCTL", serverName) + "";
                    if (cycleBankpro.startedServices == 3)
                    {
                        lblCycleBankproResult.Content = "Successfully restarted BankPro on " + serverName;
                        txtCycleBankProOutput.Text += "---------------------------------------------------------------------\n";
                        txtCycleBankProOutput.Text += "Successfully restarted BankPro on " + serverName;
                    }
                });





public string StopService(string serviceName, string serverName)
        {
            string output = string.Empty;
            ServiceController[] controller = null;
            try
            {
                controller = ServiceController.GetServices(serverName);
            }
            catch (Exception oE)
            {
                Console.WriteLine(oE.Message);
                return oE.Message;
            }
            foreach (ServiceController svc in controller)
            {
                if (svc.ServiceName == serviceName)
                {
                    output += "Current status of " + svc.ServiceName + "( " + svc.DisplayName + ")" + ":" + svc.Status + "\n";
                    if (svc.Status == ServiceControllerStatus.Running)
                    {
                        output += "Stopping " + svc.ServiceName + "( " + svc.DisplayName + ")" + "...\n";
                        try
                        {
                            svc.Stop();
                            svc.WaitForStatus(ServiceControllerStatus.Stopped);
                            output += "Service " + svc.ServiceName + "( " + svc.DisplayName + ")" + " is now " + svc.Status + "\n";
                            return output;
                        }
                        catch (Exception ex)
                        {
                            output = ex.Message;
                            return output;
                        }
                    }
                    else
                    {
                        output = svc.ServiceName + " is already stopped";
                        return output;
                    }
                }
            }
            return "Service with name " + serviceName + " was not found!";
        }
        public string StartService(string serviceName, string serverName)
        {
            ServiceController[] controller = null;
            string output = string.Empty;
            try
            {
                controller = ServiceController.GetServices(serverName);
            }
            catch (Exception oE)
            {
                return oE.Message;
            }
            foreach (ServiceController svc in controller)
            {
                if (svc.ServiceName == serviceName)
                {
                    output = "Current status of " + svc.ServiceName + "( " + svc.DisplayName + ")" + ":" + svc.Status;
                    if (svc.Status == ServiceControllerStatus.Stopped)
                    {
                        output += "\nStarting " + svc.ServiceName + "( " + svc.DisplayName + ")" + "...\n";
                        try
                        {
                            svc.Start();
                            svc.WaitForStatus(ServiceControllerStatus.Running);
                            output += "Service " + svc.ServiceName + "( " + svc.DisplayName + ")" + " is now " + svc.Status + "\n";
                        }
                        catch (Exception ex)
                        {
                            output += "\n" + ex.Message;
                        }
                    }
                    else
                    {
                        output += svc.ServiceName + " was already running.\n";
                    }
                    if (svc.Status == ServiceControllerStatus.Running)
                    {
                        startedServices++;
                        return output;
                    }
                }
            }
            output = "Service with name " + serviceName + " was not found!";
            return output;
        }

推荐答案

您的问题非常正确:您需要完全重新设计代码才能使用线程.写noe,它不是多线程的.甚至不要玩弄没有线程的想法.

熟悉Dispatcher很好,但是您误用了它.仅当您具有UI线程并且要从另一个线程触发某些操作时,才可以使用分派器.我在此处提供了详细的说明和基本用法说明: Control.Invoke()与Control .BeginInvoke() [ ^ ].

根据经验,使用DispatcherPriority是没有意义的.最好不要碰任何优先事项,直到您确切知道为什么要这样做,这是非常罕见的情况.

有关使用线程的类似情况,请参见: Treeview问题扫描仪和MD5 [ ^ ].

基本上,您需要创建至少一个线程来执行所有及时的操作.线程不应使用自旋等待:有线程同步原语可以使线程等待而不会浪费CPU时间. UI应该仅将任务提供给线程.一种通用的方法是通过阻塞队列发送消息.请参阅有关以下主题的提示/技巧"文章:简单阻止队列用于线程通信和线程间调用 [ ^ ].

对于启动线程,我强烈建议使用线程包装器传递任何参数.请参见:如何将ref参数传递给线程 [ ^ ].

您需要尝试重新设计基于线程的应用程序.如果您遇到任何问题,请询问其他问题.

—SA
Your question is very rightful: you need to redesign you code completely to use thread. Write noe, it is not multithreaded. Don''t even play with the idea to go along without threads.

It''s good that you are familiar with Dispatcher, but you misused it. Dispatcher is only usable when you have UI thread and want to trigger some operation from the other thread. I provided detail explanations and basic usage directions here: Control.Invoke() vs. Control.BeginInvoke()[^].

As a rule of thumb, using DispatcherPriority is pointless. Better don''t touch any priorities, until you know exactly why you do it, which would be quite a rare case.

For a similar case of use of a thread, see this: Problem with Treeview Scanner And MD5[^].

Basically, you need to create at least one thread to carry out all your timely operations. Thread should not use spin-wait: there are thread synchronization primitives to make a thread waiting without wasting CPU time. The UI should only feed the task to the thread. One general method of doing that is sending messages via blocking queue. Please see my Tips/Tricks article on the topic: Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

For starting a thread, passing any parameters I strongly recommend using a thread wrapper; please see this: How to pass ref parameter to the thread[^].

You need to try to re-design the application to be based on threading. Ask further Questions if your face any problems.

—SA


在这种情况下,我建议您使用BackgroundWorker对象,该对象具有完全控制开始,停止,完成和进行的功能.

以及任何 SA [C# WPF项目线程-需要帮助 [ Silverlight中的BackgroundWorker [使用异步处理的WPF应用程序的响应UI [
I would suggest you to use BackgroundWorker object in this case which has complete control to start, stop, completed and progression.

And whatever SA[^] mentioned in the C# WPF Project Threading - Need Help[^] also make sence.


Examples:
BackgroundWorker in Silverlight[^]

Responsive UIs for WPF Applications Using Asynchronous Processing[^]

Mark it as Answer, if it is helpful


这篇关于C#WPF项目线程-需要帮助的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆