【发布时间】:2013-05-03 18:30:28
【问题描述】:
所有,我在运行时从 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 活动/打开的最佳方法是什么?
感谢您的宝贵时间。
编辑。按照下面 Stephen 的建议,我决定将我的 DLL intery 方法类型转换为 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 关键字发生的链接 - 即创建调用方法(调用 Task<String> 等类型的 DLL . 向上调用堆栈。
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 的调用(注意调用方法已经在后台线程池线程上运行)。
感谢任何进一步的帮助。
【问题讨论】:
-
尽量不要踢开的门:不要关门。 Boilerplate 是 BackgroundWorker.RunWorkerCompleted 和 TaskScheduler.FromCurrentSynchronizationContext,用于在工作人员完成后在 UI 线程上运行代码。
-
对不起,我不明白你的意思@HansPassant。感谢您的宝贵时间...
-
@HansPassant BackgroundWorker 或多或少已经过时并被认为是遗留问题。它除了对 Task 和 Progress 的简单调用之外没有任何作用,不能异步提供详细的进度,不能用于链接多个异步调用,不能使用 ThreadPool,不能利用异步方法,不能……
-
@PanagiotisKanavos - BackgroundWorker 通过 SynchronizationContext 类使用 ThreadPool。它的进度也使用 ThreadPool 报告。
标签: winforms dll task-parallel-library async-await c#-5.0