Visual Studio delay between multiple startup proje

2020-05-29 20:09发布

问题:

how to add some delay between startup projects in solution?

I want Client project to be started after 2-3 seconds from starting WindowsService.

Why I need this?

WindowsService runs socket server and Client runs socket to connect to server. WindowsService loads slowly than Client, and this causes an exception on client side when connecting to server which is not run yet

回答1:

I would probably add a retry mechanism within the client. That way not only does it help in the "starting up from Visual Studio" case - it also helps if the server happens to be restarting while the real client connects. The fact that the server is on a faster machine doesn't mean the server will never need to restart, does it?

Indeed, you may well want to add this retry mechanism in such a way that the client can recover even if the server is restarted while it's connected. It depends on what the project is doing, of course.



回答2:

You can use Mutex locking to sync the two startup project.

Program 1 (StartUp Project 1):

    namespace ConsoleApplication1
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;

    class Program1
    {
        private static  bool isNewMutexCreated = true;
        private static Mutex mutex;
        static void Main(string[] args)
        {
            mutex = new Mutex(true, "Global\\ConsoleApplication1", out isNewMutexCreated);
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
            Console.WriteLine("Application1 executed on " + DateTime.Now.ToString());

            Console.ReadKey();
        }

        static void CurrentDomain_ProcessExit(Object sender, EventArgs e)
        {
            if (isNewMutexCreated)
            {
                Console.WriteLine("Mutex Released");
                mutex.ReleaseMutex();
            }
        }

    }
}

Program 2 (StartUp Project 2):

namespace ConsoleApplication2
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;
    using System.Threading;

    class Program2
    {
        static void Main(string[] args)
        {
            Mutex mutex = null;
            Thread.Sleep(5000);

            while (mutex == null)
            {
                try
                {
                    mutex = Mutex.OpenExisting("Global\\ConsoleApplication1");

                }
                catch (Exception)
                {
                    Console.WriteLine("Mutex not found on " + DateTime.Now.ToString());
                    Thread.Sleep(3000);
                }


            }
            Console.WriteLine("Application2 executed on " + DateTime.Now.ToString());
            Console.ReadKey();
        }
    }
}


回答3:

Another simpler option for testing is to just delay the client if the debugger is attached like this:

if (System.Diagnostics.Debugger.IsAttached)
{
    System.Threading.Thread.Sleep(2000);
}

You might wrap that in an #if DEBUG block if you like. Anyway I think this should be the least amount of work :)



回答4:

In case of multiple start-up projects, they are loaded in the order they are specified neither simultaneously nor randomly. http://msdn.microsoft.com/en-us/library/09138bex(v=vs.90).aspx

So ,may be if you specify "client" after "window service", then it may workout fine. And if you don't want to got the coded way suggested above, then (for testing only) you can manually attach the "client" process to you solution from a different solution after your desired delay. http://msdn.microsoft.com/en-us/library/c6wf8e4z(v=vs.100).aspx



回答5:

If the client needs to be started after, you need to adjust your list, as at the moment its started before!

I would also code a "/wait" which on loading app if it finds that flag, waits for it maybe useful in use too.



回答6:

You can set the server project as the single startup project and use this macro to launch the server and the client with a delay:

Sub DebugServerAndClientWithDelay()
    DTE.Debugger.Go(False)
    System.Threading.Thread.Sleep(2000)
    DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
    DTE.ActiveWindow.Object.GetItem("SolutionName\ClientProjectName").Select(vsUISelectionType.vsUISelectionTypeSelect)
    DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub

You can add a button to your toolbar or use a shortcut key to run this macro.



回答7:

Why don't you just pass an argument to the client application which sets the delay?

static void main(string[] args)
{
  // Sleep some time
  int delay;
  if (args.Length > 0 && int.TryParse(args, out delay))
  {
    Thread.Sleep(delay);
  }

  // Initialize client
}

Now you can add the delay in milliseconds to the command-line arguments for the project startup.

I also agree that if possible, it's better to solve your problem structurally, so it doesn't matter when your client and server start.



回答8:

Just add a procedure to check whether the socket is open or not. If the socket is open continue executing your code and try checking again if the socket is not open. This way even if you start the windows service later there will be no problem.



回答9:

For the n-tier application I am currently working on, I combined the Mutex method suggested by Romil (slightly different code but same principle) and encapsulated it within a method with a [Conditional("DEBUG")] attribute applied (so it gets stripped out in release mode). We also surround the mutex logic with if (System.Diagnostics.Debugger.IsAttached) {...} since QA builds use Debug mode.

We originally just used a Thread.Sleep with a wait period that worked for most developers machines, but we ran into problems because devs' computer speeds vary and as we added more and more to the server bootstrapper, we had to keep increasing the wait period.