We have a console application named EC. We got a recent requirement from the customer to show a form from this console application. We have displayed the form with the following source code
ModuleInitializerForm moduleInitializerDlg = new ModuleInitializerForm()
{
Parent = parent,
TopMost = true,
TopLevel = true,
Text = Common.MESSAGE_INFO_TITLE,
ControlBox = false,
FormBorderStyle = FormBorderStyle.FixedDialog,
KeyPreview = false,
};
moduleInitializerDlg.Initialize();
moduleInitializerDlg.ShowDialog();
The purpose of this form is to display the module initialization status. The form will receive module initialization status as events from other components. It automatically closes, when it receives the last module initializati开发者_开发技巧on completed/failed event. The source code of the form is given below.
The issue is sometimes the OnModuleInitializationCompleted method will block with the following log entries. The first log entry is from the event callback thread and the second log entry is from the form thread. As per the source code, the method CheckIfAllModulesInitComplete should be invoked. But it is not happening. Can you help me to solve the problem?
[32][4/26/2011 17:43:15:828]-INFO-[ThreadId = 5332, OnModuleInitializationCompleted]-Received STAGE
[33][4/26/2011 17:43:15:828]-INFO-[ThreadId = 6132, OnModuleInitializationCompleted]-Received STAGEForm Source Code
internal partial class ModuleInitializerForm : Form
{
private List<ModuleData> _moduleDataList = new List<ModuleData>();
private List<MessageData> _messageList = new List<MessageData>();
delegate void ECEventsHandler(object sender, EventArgs e);
public ModuleInitializerForm()
{
InitializeComponent();
InitializeFootPrintControl();
}
internal void Initialize()
{
IEquipmentControl equipMentControl = null;
ConnectToEquipmentControl(out equipMentControl);
ReadOnlyCollection<IModule> moduleList = equipMentControl.GetAllModules();
foreach (IModule module in moduleList)
{
this._moduleDataList.Add(new ModuleData(module));
module.InitializationStarted += new EventHandler(OnModuleInitializationStarted);
module.InitializationCompleted += new EventHandler(OnModuleInitializationCompleted);
}
this._moduleStatusGrid.DataSource = this._moduleDataList.ToArray();
this._footprint.Activate();
}
public void OnModuleInitializationCompleted(object sender, EventArgs e)
{
ModuleStatusWindow.Logger.LogMessage("OnModuleInitializationCompleted", LogMessageType.Information, "Received {0}", (sender as IModule).Name);
if (this.InvokeRequired)
{
this.BeginInvoke(new ECEventsHandler(OnModuleInitializationCompleted), sender, e);
}
else
{
CheckIfAllModulesInitComplete();
}
}
private void CheckIfAllModulesInitComplete()
{
ModuleStatusWindow.Logger.LogMessage("CheckIfAllModulesInitComplete", LogMessageType.Information, "Enter >>");
this._moduleStatusGrid.DataSource = this._moduleDataList.ToArray();
this._moduleStatusGrid.Invalidate();
ModuleStatusWindow.Logger.LogMessage("CheckIfAllModulesInitComplete", LogMessageType.Information, "Updated grid control...");
if (this._moduleDataList.Count(moduleData => !moduleData.IsInitOver) == 0)
{
this._footprint.DeActivate();
ModuleStatusWindow.Logger.LogMessage("CheckIfAllModulesInitComplete", LogMessageType.Information, "Stopping message listenr...");
ClientMessageListner.Stop();
ModuleStatusWindow.Logger.LogMessage("CheckIfAllModulesInitComplete", LogMessageType.Information, "Closing Window...");
this.Close();
}
ModuleStatusWindow.Logger.LogMessage("CheckIfAllModulesInitComplete", LogMessageType.Information, "Leave <<");
}
public void OnModuleInitializationStarted(object sender, EventArgs e)
{
ModuleStatusWindow.Logger.LogMessage("OnModuleInitializationStarted", LogMessageType.Information, "Received {0}", (sender as IModule).Name);
if (this.InvokeRequired)
{
this.BeginInvoke(new ECEventsHandler(OnModuleInitializationStarted), sender, e);
}
else
{
ModuleStatusWindow.Logger.LogMessage("OnModuleInitializationStarted", LogMessageType.Information, "Updating the grid...");
this._moduleStatusGrid.DataSource = this._moduleDataList.ToArray();
this._moduleStatusGrid.Invalidate();
ModuleStatusWindow.Logger.LogMessage("OnModuleInitializationStarted", LogMessageType.Information, "Updated module status grid.");
}
}
private void ConnectToEquipmentControl(out IEquipmentControl equipMentControl)
{
ServerConfig equipmentConfig = ICECommonInterface.GetServerConfiguration("ICEEquipmentControl");
TcpChannel clientChannel = null;
equipMentControl = RemoteConnectionManager.RegisterClient<IEquipmentControl>(equipmentConfig, out clientChannel);
}
private void InitializeFootPrintControl()
{
this._footprint.ImportConfiguration(ICECommonInterface.ConfigPath + @"\FootPrintConfig.xml");
this._footprint.Initialize();
}
}
According to your code, and some of you descriptions in the comment thread, it seems that your problem is that the events are not being captured, and in turn the 'OnModuleInitializationCompleted' method can't be invoked. Of course the threading model plays a part in all of this.
Single Thread:
You have a console application that it likely running out of a single thread, so your problem is that the dialog itself is blocking the initialization of the modules. Take a look at the pseudo code below....
modDialog.Initialize();
// This is a blocking call. The program will wait until the dialog is closed!
modDialog.ShowDialog();
// This is where the mods are initialized, but it is waiting for the dialog to close,
// and the dialog is waiting on the initialization of the modules.
InitModules();
Of course I probably don't need to mention that mixing dialogs into console applications is just plain silly, but necessity makes for strange bedfellows I suppose....
Here are some options:
1. Use the console to display the initialization messages rather than a dialog. (best)
2. Use Dialog.Show() which is non-blocking, but the user can close it if they want (better)
3. Run the init each of the modules from within the dialog itself (total hack)
Multi-Thread:
On the other hand, these kinds of things in multi-threaded code can be really tricky to see. For example, your event handlers may be valid, but by the time they are set up, the events they intend to capture have already been fired, and so you don't actually catch them.
精彩评论