Вопрос

Is there any problem which i have to do carefully when starting new process in multiple thread application?

I tried this in a simple project:

static void Main(string[] args)
{
    Process.Start(@"D:\System\Desktop\a.txt");
    MessageBox.Show("Success");
}

And it runs perfectly. But when i do it in my big project which use multiple thread, it's thread is stopped working ("a.txt" is opened but "Success" is not shown) while my application (other thread) do well.

What is the problem in this situation?

Это было полезно?

Решение

If you have a Windows.Forms application and you try to show a message-box from a thread that is not the main user-interface thread, the behavior of the message-box is undefined. Meaning, it may or may not show, be inconsistent, or some other problem.

For instance, displaying a message-box from the BackgroundWorker's DoWork event may or may not work. In one case, the message-box-result was always cancel regardless of what button was clicked.

Therefore, if you are using a message-box just for debugging purposes, use a different technique. If you have to show a message-box, call it from the main user-interface thread.

A console-application should normally not have problems displaying message-boxes. Yet, I have had cases where I would have to sleep the thread for 100ms before the message-box call.

Note, as TomTom pointed out, the main user-interface thread is the application's Windows message loop. Which reminds me, I once had to create a Form in a Console application in order to create a Windows message loop, so my application could respond to Windows messages.

Другие советы

This isn't the answer - I can't put all this code in a comment...

This works for me. Tell me how your code differs from this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.IO;

namespace Test
{
    class Program
    {
        const string OutputFile = @"E:\Output.txt";

        object _lock = new object();

        static void Main(string[] args)
        {
            Program program = new Program();

            Thread thread = new Thread(program.ThreadMethod);
            thread.Start(@"E:\Test.txt");

            thread = new Thread(program.ThreadMethod);
            thread.Start(@"E:\DoesntExist.txt");

            Console.ReadKey();
        }

        void ThreadMethod(object filename)
        {
            String result = RunNormal(filename as string);
            lock (_lock)
            {
                FileInfo fi = new FileInfo(OutputFile);
                if (!fi.Exists)
                {
                    try
                    {
                        fi.Create().Close();
                    }
                    catch (System.Security.SecurityException secEx)
                    {
                        Console.WriteLine("An exception has occured: {0}", secEx.Message);
                        return;
                    }
                }

                StreamWriter sw = fi.AppendText();
                sw.WriteLine(result);
                sw.Close();
            }
        }

        string RunNormal(string fullfilename)
        {
            try
            {
                Process.Start(fullfilename);
                return fullfilename + "|Success";
            }
            catch (Exception e)
            {
                return fullfilename + "|" + e.ToString();
            }
        }
    }
}

The output in Output.txt is:

E:\DoesntExist.txt|System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
   at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start()
   at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
   at System.Diagnostics.Process.Start(String fileName)
   at Test.Program.RunNormal(String fullfilename) in E:\Projekti\VS2010\Test\Test\Program.cs:line 59
E:\Test.txt|Success

How much different is your code? Do you call some other methods? How do you process the results?

Make sure Process.Start works. Passing a filename is not good enough in some cases. In you sample code, you would have to set the use-shell property; otherwise, you would have to use cmd start <filename> or equivalent.

Therefore, just start NotePad.exe to make sure Process.Start works. If it does then your problem is the process command and command line.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top