如何在解决方案中的启动项目之间添加一些延迟?
我希望在启动 WindowsService 后 2-3 秒后启动客户端项目。
为什么我需要这个?
WindowsService 运行套接字服务器,客户端运行套接字连接服务器。WindowsService 加载速度比客户端慢,这会导致客户端在连接到尚未运行的服务器时出现异常
如何在解决方案中的启动项目之间添加一些延迟?
我希望在启动 WindowsService 后 2-3 秒后启动客户端项目。
为什么我需要这个?
WindowsService 运行套接字服务器,客户端运行套接字连接服务器。WindowsService 加载速度比客户端慢,这会导致客户端在连接到尚未运行的服务器时出现异常
我可能会在客户端中添加重试机制。这种方式不仅有助于“从 Visual Studio 启动”的情况 -如果服务器碰巧在真正的客户端连接时重新启动,它也会有所帮助。服务器位于更快的机器上这一事实并不意味着服务器永远不需要重新启动,不是吗?
实际上,您可能希望以这样一种方式添加此重试机制,即使服务器在连接时重新启动,客户端也可以恢复。当然,这取决于项目在做什么。
您可以使用互斥锁来同步两个启动项目。
计划 1(启动项目 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();
}
}
}
}
计划 2(启动项目 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();
}
}
}
另一个更简单的测试选项是,如果调试器是这样连接的,则延迟客户端:
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(2000);
}
如果您愿意,可以将其包装在一个#if DEBUG
块中。无论如何,我认为这应该是最少的工作量:)
如果有多个启动项目,它们的加载顺序既不是同时也不是随机指定的。 http://msdn.microsoft.com/en-us/library/09138bex(v=vs.90).aspx
所以,如果你在“窗口服务”之后指定“客户端”,那么它可能会很好。如果您不想获得上面建议的编码方式,那么(仅用于测试)您可以在您想要的延迟后从不同的解决方案手动将“客户端”进程附加到您的解决方案。 http://msdn.microsoft.com/en-us/library/c6wf8e4z(v=vs.100).aspx
如果客户端需要在之后启动,您需要调整您的列表,就像之前启动的那一刻一样!
我还会编写一个“/wait”,如果它在加载应用程序时找到该标志,等待它可能在使用中也很有用。
您可以将服务器项目设置为单个启动项目,并使用此宏延迟启动服务器和客户端:
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
您可以在工具栏中添加一个按钮或使用快捷键来运行此宏。
只需添加一个程序来检查套接字是否打开。如果套接字打开,请继续执行您的代码并尝试再次检查套接字是否未打开。这样即使以后再启动windows服务也不会有问题。
对于我目前正在处理的 n 层应用程序,我结合了 Romil 建议的 Mutex 方法(代码略有不同但原理相同)并将其封装在一个应用了 [Conditional("DEBUG")] 属性的方法中(所以它得到在发布模式下被剥离)。我们还使用 if (System.Diagnostics.Debugger.IsAttached) {...} 包围互斥逻辑,因为 QA 构建使用调试模式。
我们最初只是使用了一个 Thread.Sleep,它对大多数开发人员的机器都有效,但我们遇到了问题,因为开发人员的计算机速度各不相同,并且随着我们向服务器引导程序添加越来越多的内容,我们不得不不断增加等待时间.
为什么不直接将参数传递给设置延迟的客户端应用程序?
static void main(string[] args)
{
// Sleep some time
int delay;
if (args.Length > 0 && int.TryParse(args, out delay))
{
Thread.Sleep(delay);
}
// Initialize client
}
现在,您可以将延迟(以毫秒为单位)添加到项目启动的命令行参数中。
我也同意,如果可能的话,最好从结构上解决您的问题,因此您的客户端和服务器何时启动并不重要。