Click here to Skip to main content
15,878,231 members
Please Sign up or sign in to vote.
4.00/5 (2 votes)
See more:
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.

C#
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;
                    }
                });


C#
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;
        }
Posted

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
 
Share this answer
 
Comments
Tarun.K.S 3-Mar-11 1:03am    
Well explained! 5d!
Sergey Alexandrovich Kryukov 3-Mar-11 2:17am    
Thank you.
--SA
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
 
Share this answer
 
v3
Comments
Tarun.K.S 3-Mar-11 0:58am    
Exactly! BackgroundWorker is recommended for WPF and it also brings the goodies like cancelling and reporting progress for progress bar. My 5!
Venkatesh Mookkan 3-Mar-11 1:01am    
Thank you.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900