2

全部,我在运行时从 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 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关键字发生的链接 - 即使调用方法(调用类型的 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的调用(注意调用方法已经在后台线程池线程上运行)。

任何进一步的帮助表示赞赏。

4

2 回答 2

4

更改ExecutetoTaskawaitit 的返回类型。

于 2013-05-09T12:14:14.203 回答
1

很难猜出你在 dll 中有什么,但最终你的 dll 代码 + 暴露在你的问题中:

dllWinForm.Show();  

最终应该是在并列之后:

new Thread
      (   
         () => new Form().ShowDialog()
       )
       .Start();  

可能, 您应该更改dllWinForm.Show();;dllWinForm.ShowDialog().Start()

ShowDialog()与之相反Show()它开始自己的消息泵送,并且仅在显式关闭时才返回

更新(回应评论):
从 UI 启动表单并不是绝对必要的。
由于您使用的是 .NET 4.5,因此使用 WPF(而不是 Windows 窗体)表单可能更简单。
这是WPF 表单的代码 ,为了适应 Windows 表单,您应该Dispatcher通过初始化WindowsFormsSynchronizationContext来更改部分

虽然,IMO,WinForms 代码会复杂得多。

于 2013-05-14T20:11:53.437 回答