すべて、実行時に WinForm C# アプリケーションから WinForm を含む .NET DLL を呼び出します。これを行うには、次を使用します。
DLL = Assembly.LoadFrom(strDllPath);
classType = DLL.GetType(String.Format("{0}.{1}", strNamespaceName, strClassName));
if (classType != null)
{
if (bDllIsWinForm)
{
classInst = Activator.CreateInstance(classType);
Form dllWinForm = (Form)classInst;
dllWinForm.Show();
// Invoke required method.
MethodInfo methodInfo = classType.GetMethod(strMethodName);
if (methodInfo != null)
{
object result = null;
result = methodInfo.Invoke(classInst, new object[] { dllParams });
return result == null ? String.Empty : result.ToString();
}
}
}
これは、WinForm DLL と、DLL 内のシリアル メソッドに必要なメソッドを呼び出しています。ただし、現在、マルチスレッド DLL を呼び出して、次のメソッドを呼び出しています。
public async void ExecuteTest(object[] args)
{
Result result = new Result();
if (!BuildParameterObjects(args[0].ToString(), args[1].ToString()))
return;
IProgress<ProgressInfo> progressIndicator = new Progress<ProgressInfo>(ReportProgress);
List<Enum> enumList = new List<Enum>()
{
Method.TestSqlConnection,
Method.ImportReferenceTables
};
Task task = Task.Factory.StartNew(() =>
{
foreach (Method method in enumList)
{
result = Process.ProcessStrategyFactory.Execute(Parameters.Instance, progressIndicator,
Process.ProcessStrategyFactory.GetProcessType(method));
if (!result.Succeeded)
{
// Display error.
return;
}
}
});
await task;
Utilities.InfoMsg("VCDC run executed successfully.");
}
await
しかし、これは(予想される)ためにすぐに呼び出し元に制御を返しています。ただし、リターンによって呼び出し元のメソッドが終了し、DLL WinForm が閉じられます。
DLL WinForm をアクティブ/オープンにしておく最善の方法は何ですか?
御時間ありがとうございます。
編集。以下のスティーブンの提案に従って、DLLのインターリーメソッドタイプを次のように変更Task<object>
し、継続を設定することにしました
if (classType != null)
{
if (bDllIsWinForm)
{
// To pass object array to constructor use the following.
// classInst = Activator.CreateInstance(classType, new object[] {dllParams});
classInst = Activator.CreateInstance(classType);
dllWinForm = (Form)classInst;
dllWinForm.Show();
// Invoke required method.
MethodInfo methodInfo = classType.GetMethod(strMethodName);
if (methodInfo != null)
{
object result = null;
result = methodInfo.Invoke(classInst, new object[] { dllParams });
if (result != null)
{
if (result.GetType() == typeof(Task<object>))
{
Task<object> task = (Task<object>)result;
task.ContinueWith(ant =>
{
object innerResult = task.Result;
return innerResult == null ? String.Empty : innerResult.ToString();
});
}
return result.ToString();
}
return String.Empty;
}
}
}
await
キーワードで発生するチェーン化を回避するために、代わりに継続を設定することにしましたawait
-つまり、呼び出しメソッドを作成します(型のDLLTask<String>
などを呼び出しスタックに呼び出します.
DLL エントリ メソッドは次のようになります。
public Task<object> ExecuteTest(object[] args)
{
Task<object> task = null;
Result result = new Result();
if (!BuildParameterObjects(args[0].ToString(), args[1].ToString()))
return task;
IProgress<ProgressInfo> progressIndicator = new Progress<ProgressInfo>(ReportProgress);
List<Enum> enumList = new List<Enum>()
{
Method.TestSqlConnection,
Method.ImportReferenceTables
};
task = Task.Factory.StartNew<object>(() =>
{
foreach (Method method in enumList)
{
result = Process.ProcessStrategyFactory.Execute(Parameters.Instance, progressIndicator,
Process.ProcessStrategyFactory.GetProcessType(method));
if (!result.Succeeded)
{
// Display error.
}
task.Wait(5000); // Wait to prevent the method returning too quickly for testing only.
}
return null;
});
return task;
}
しかし、これにより DLL WinForm が一瞬だけ表示されてから消えてしまいます。Form dllWinForm
オブジェクトへの参照をアクティブに保つためにグローバルを作成しようとしましたが、これも機能しませんでした。DLL への呼び出しに注意してください (注: 呼び出し元のメソッドは既にバックグラウンド スレッド プール スレッドで実行されています)。
さらに助けていただければ幸いです。