winforms - 在运行时调用多线程 DLL

标签 winforms dll task-parallel-library async-await c#-5.0

所有,我在运行时从 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 global 来保持对对象的引用处于事件状态,但这也不起作用。我想指出的是对 DLL 的调用(注意,调用方法已经在后台线程池线程上运行)。

如有任何进一步的帮助,我们将不胜感激。

最佳答案

Execute的返回类型更改为Taskawait它。

关于winforms - 在运行时调用多线程 DLL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16459102/

相关文章:

c# - WinApp 窗体在 Load 事件期间加载过多数据

c++ - Visual Studio 2012升级后出现"Module was built without symbols"错误

visual-studio - 使用 VS 将 C++ 库编译为静态库和动态 dll

c# - 将 ContinueWith 用作 "finally"操作是否安全?

c# - 如何将面板添加到 SplitContainer?

c# - 检测是否显示工具提示?

c# - 如何正确停止正在使用 Control.Invoke 的线程

c++ - 已编译的应用程序想要从绝对路径加载 DLL

.net - 如何取消Task.WhenAll?

c# - 在 C# 中,我正在调用一个公共(public) API,它的 API 限制为每秒 10 次调用