2013-05-09 19 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

相關問題