WINFORM 启动器(并行exe)设计方案

一、故事线

当已经有一个完整的项目方案,突然提出需要增加功能支持并行的需求时,通常考虑项目中模块是否支持并行,比如使用了单例模式时,又要模块区分,单例模块将需要修改等等问题。

此时,可以采用启动器方式实现,该方式的优点是:已完成项目只需要增加启动标识的相关功能即可,其他功能可直接使用,极大缩短功能并行的开发周期。

二、启动器

我的项目中需要的启动器本身也是一个winform程序,其中包含多个按钮对应并行多个并行程序,点击按钮后打开一个程序副本。

需要考虑的问题:

1 每个副本只允许执行一次,比如支持四个副本,那么一共只能有一个副本(当然,这是我的需求,如果不考虑可以不做限制),需要做副本检查的方案。

2 单个副本内的项目静态变量是否共享问题。如果共享的话这个方案将失效。经过验证是独立的。

3 如何启动新的exe程序。

三、启动器实现

1 程序可以多开,但启动器必然只能运行一个,此时使用Mutex实现:

var mutex = new Mutex(true, key, out result);

- key为一个唯一标识

- result为结果,如果为false,表示已标记,如果只有你的程序进行该key的设置,那么你的程序已经启动了。

2 启动器中,打开副本程序,使用以下代码:

Process myprocess = new Process();
ProcessStartInfo startInfo = new ProcessStart(path, args);
myprocess.StartInfo = startInfo;
myprocess.StartInfo.UseShellExecute = false;
myprocess.Start();

args为string类型的变量,如果你还熟悉以下代码,那么应该args的第一个元素即为当前的args变量。

path为打开程序路径,注意必须是绝对路径。

/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main(string[] args)
{
     //...
}

3 启动器中的副本检查方案,由于单个副本只能打开一次,启动器需要持续跟进副本是否已经终结,并允许用户重启开启。我采用的方案是通过ini配置文件实现:

FileTooler.IniWriteValue("STARTUP", $"CHN{index}", "1", CONFIG_PAHT);

FileTooler.IniWriteValue是我封装的ini方法,具体ini操作参照以下内容:

[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section
    , string key
    , string val
    , string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section
    , string key
    , string def
    , StringBuilder retVal
    , int size
    , string filePath);

这里的关键是第二个参数$"CHN{index}",index对应副本编号,"1"表示开启。

同理,对应的副本程序关闭时,应当调用以下代码更新ini文件。

FileTooler.IniWriteValue("STARTUPA20", $"CHN{index}", "0", CONFIG_PAHT);

除了开始副本时和结束副本时设置ini文件外,需要增加一个timer进行持续检查:

private void timer1_Tick(object sender, EventArgs e)
{
    for (int i = 0; i < 4; i++)
    {
        var chk = Syscan.File.FileTooler.IniReadValue("STARTUPA20", $"CHN{index}", CONFIG_PAHT)=="1";
        btns[i].Text = $"通道{index}" + (chk? " 已启动" : "");
        btns[i].Enabled = !chk;
    }
}

这里可以看出对应的通道设置的是button控件,通过enable和文字描述提醒用户是否可以重新开启。

Timer的使用也不再这里赘述,不了解的请移步:

https://msdn.microsoft.com/zh-cn/library/system.windows.forms.timer.aspx

四、其他

 在这个框架下如果想支持部分数据共享,最简单的方案是把共享部分放在一个数据库中,非共享单独分放即可。

五、总结

该方案主要涉及的技术点包括:

1 基于Mutex单一进程检查

2 ini文件读写

3 Process方式启动新程序

4 Timer的使用

至此启动器方案确定,如有任何疑问可以留言。

posted @ 2017-08-31 12:20  sunlyk  阅读(521)  评论(0编辑  收藏  举报