2016-01-12 70 views
-2

顯示形式所以我有這個包含一個靜態類:從不同的線程

public static void ShowErrorReport(Exception e, SqlCommand sqlc = null) 
    { 
     try 
     { 
      frmErrorReport frmER = new frmErrorReport(e, SqlCommand_: sqlc); 
      frmER.ShowDialog(); 
      frmER.Dispose(); 
     } 
     catch (Exception f) 
     { 
      Debug.Print(f.ToString()); 
     } 
    } 

我希望能夠使用這個從在排隊的後臺工作運行一些數據庫相關的方法。問題是這些方法有時不知道任何winforms對象,所以使用Invoke()是不可能的(據我所知)。

是否有任何其他方式從backgroundworker線程調用此過程並確保在UI線程上創建表單?

或者我會通過傳遞一個winforms對象來讓這些數據庫方法有點混亂(不期待這種可能性!)?

我是很新,多線程...

感謝

+1

這是糟糕的設計。更好地使用事件或例外。這也與多重流行無關。 – CSharpie

+0

謹慎闡述? –

+0

如何使用服務中的確切代碼,其中沒有用戶可以單擊對話框?記住這一點,即使你不需要它。它仍然有助於避免這樣的問題。 – CSharpie

回答

0

我希望能夠使用這個從在排隊的後臺工作運行一些數據庫相關的方法。問題是這些方法有時不知道任何winforms對象,所以使用Invoke()是不可能的(據我所知)。

如果您的後臺代碼需要與UI進行交互,您需要通過某種方式正確地與UI交談。通常情況下,要創建一個可以傳遞給你的類的「交互服務」,然後這個交互服務會調用你需要的任何UI技術。

public BackgroundClass 
{ 
    public BackgroundClass(IInteractionService interactionService) 
    { 
     _interactionService = interactionService; 
    } 

    private readonly IInteractionService _interactionService; 

    public static void ShowErrorReport(Exception e, SqlCommand sqlc = null) 
    { 
     try 
     { 
      _interactionService.ShowErrorReportDialog(e, sqlc); 
     } 
     catch (Exception f) 
     { 
      Debug.Print(f.ToString()); 
     } 
    } 
} 

public interface IInteractionService 
{ 
    void ShowErrorReportDialog(Exception e, SqlCommand cmd); 
} 

public class WinFormsInteractionService : IInteractionService 
{ 
    public WinFormsInteractionService() 
     this(SynchronizationContext.Current) 
    { 
    } 

    public WinFormsInteractionService(SynchronizationContext syncContext) 
    { 
     if(syncContext == null) 
      throw new ArgumentNullException("syncContext"); 
     _syncContext = syncContext; 
    } 

    private readonly SynchronizationContext _syncContext; 

    public void ShowErrorReportDialog(Exception e, SqlCommand cmd) 
    { 
     _syncContext.Send(s => 
     { 
      using(frmErrorReport frmER = new frmErrorReport(e, SqlCommand_: cmd)) 
      { 
       frmER.ShowDialog(); 
      } 
     }); 
    } 
} 

如果你決定從的WinForms切換到WPF甚至安慰你BackgroundClass不需要做任何改變,你只需要做出的任何UI技術使用的是實現IInteractionService一個新的類。

public class ConsoleInteractionService : IInteractionService 
{ 
    public WinFormsInteractionService() 
    { 
    } 

    private readonly string _showErrorReportDialogFormatString = //... 

    public void ShowErrorReportDialog(Exception e, SqlCommand cmd) 
    { 
     Console.WriteLine(_showErrorReportDialogFormatString, e, cmd); 
     Console.WriteLine("Press enter to continue"); 
     Console.ReadLine(); 
    } 

}