2013-05-09 71 views
2

所有我在WinForm C#应用程序运行时调用一个包含WinForm的.NET DLL。要做到这一点我使用以下内容:在运行时调用一个多线程的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关键字出现 - 即拍即调用方法(即调用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显示一秒钟,然后disapear。我甚至试图让全球范围内的对象保持活动状态,但这也不起作用。我想要注意的是,调用DLL(N.B.的调用方法已经在后台线程池线程上运行)。

任何进一步有助于理解。

+0

试图不打开门:不要关闭它。样板是BackgroundWorker.RunWorkerCompleted和TaskScheduler.FromCurrentSynchronizationContext在工作完成后在UI线程上运行代码。 – 2013-05-09 11:40:53

+0

对不起,我不明白你的意思@HansPassant。感谢您的时间... – MoonKnight 2013-05-09 12:30:58

+0

@HansPassant BackgroundWorker或多或少已经过时并被视为遗留问题。除了对Task和Progress的简单调用,不能提供异步的详细进度,不能用于链接多个异步调用,不能使用ThreadPool,不能利用异步方法,不能... – 2013-05-09 13:51:30

回答

1

这很难猜测你在DLL中,但最终你的DLL的代码+你的问题暴露:

dllWinForm.Show(); 

最终应该已经并列后:

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

也许,你应该改变dllWinForm.Show(); by dllWinForm.ShowDialog().Start();

ShowDialog(),与Show(),starts its own message pumping and returns only when explicitly closed相反。

更新(在respnse评论):
这不是绝对必要从UI推出的一种形式。
由于您使用的是.NET 4.5,因此使用WPF(而不是Windows窗体)形式可能会更简单。
这里是the code for WPF form其中,为了调整Windows窗体,你应该通过初始化WindowsFormsSynchronizationContext

虽然改变Dispatcher部分,国际海事组织,WinForms的代码会更加复杂。

+0

+1我最终如何排序这是为了确保DLL是从UI线程调用的。然后,多线程DLL被调用,因为我有它。非常感谢你花时间陪伴。 – MoonKnight 2013-05-14 20:14:36

+0

谢谢。我更新了我的答案 – 2013-05-14 21:13:42

4

将退货类型Execute更改为Taskawait它。

+0

+1好主意,但我怎样才能做到这一点从调用者没有使调用代码非泛型?被调用的是用户调用的函数来调用它们自己的DLL。对不起,我应该提到这一点!谢谢你的时间。 – MoonKnight 2013-05-09 12:32:16

+0

我看不出像if(typeof(result)== GetType(Task))是如何等待任务的结果;'会在这里工作吗? – MoonKnight 2013-05-09 12:35:05

+1

如果结果的类型是(或源于)Task,那么你可以将它转换为Task并且等待它。 – 2013-05-09 12:38:59

相关问题