2017-11-22 9 views
0

メインスレッドのどこかに、アプリケーション時間全体を通して一度だけインスタンス化できるオブジェクトを作成する新しいスレッドを作成します。C#シングルトンオブジェクトが関与するマルチスレッド

私の主なスレッドの下に、私はこのオブジェクトをグローバル変数でもある方法で使用する関数を持っています。

私はオブジェクトが作成されたのと同じスレッドでこの関数を実行します。

質問この関数を呼び出す必要があるときにメインスレッドの決定時にこれをどのように達成できますか?

// global variable 
private static IWebDriver driver; 

// Main Thread thread creation 
Thread thread = new Thread(() => 
{ 
    driver = new ChromeDriver(@"myPath"); 
}); 
thread.Start(); 

// some click event on main thread 
myFunctionUsingDriverObject(); 

ドライバと同じスレッドで実行するように関数に指示する方法が必要です。通常はmethodInvokerを使用しますが、IWebDriverにはそのような方法はありません。では、ドライバのスレッドに関数を呼び出すことができる別の方法はありますか?

私はなぜこれをやりたいのだろうと思っている人は誰でも。それは、UIがメインスレッド上で実行されてから、メインスレッド上で実行されている場合、完了までUIがフリーズするためです。

+0

新しいスレッドを作成しないのはなぜ?最も簡単で醜いのは、新しいスレッドを作成し、 'driver'がまだ' null'であるかどうかを調べる 'while(true)'を入れ、 'myFunctionUsingDriverObject()'を続けます。 –

+0

@SoroushFalahati私はOPが "UIスレッド"と "Dispatcher.Invoke"に似た機能をWPFで実装しようとしていると考えています。これは、いくつかのオブジェクト(特にWindows UI)が、それらを作成したスレッドとは異なるスレッドから使​​用されると誤った動作をする可能性があるため、非常に一般的な要件です。 –

+0

https://stackoverflow.com/questions/30719366/run-work-onのようにhttps://www.bing.com/search?q=c%23+schedule+task+particular+threadを探していると思います固有のスレッド。 (重複することもあります) –

答えて

2

WindowsBase.dllへの参照を追加し、このコードを書く:

 private static IWebDriver driver; 

     private static Dispatcher dispatcher = null; 

     AutoResetEvent waitHandle = new AutoResetEvent(false);    
     var thread = new Thread(() => 
     { 
      dispatcher = Dispatcher.CurrentDispatcher; 
      waitHandle.Set(); 
      Dispatcher.Run(); 
     }); 
     thread.Start(); 
     waitHandle.WaitOne(); 

     // Now you can use dispatcher.Invoke anywhere you want 
     dispatcher.Invoke(() => 
     { 
      driver = new ChromeDriver(@"myPath"); 
     }); 

     // And async for not blocking the UI thread 
     dispatcher.BeginInvoke(new Action(() => 
     { 
      myFunctionUsingDriverObject(); 
     })); 

     // or using await 
     await dispatcher.InvokeAsync(() => 
     { 

     }); 

     // And when you are done, you can shut the thread down 
     dispatcher.InvokeShutdown(); 
+0

ありがとうございます!これは私の問題を解決しました! – Nulle

0

シングルトンクラスを使用することができます。または、これがすべてのアプリケーションに対して1回だけ実行できるようにするには、Mutexに基づくサービスクラスを使用します。これは、より多くの適用思えるように私は私が今

public interface IDriverService 
{ 
    void StartDriverService(); 
    void StopDriverService(); 
    void PerformDriverAction(); 
} 

作る実装できる限り、あなたの元を表示します

public class ChromeDriverService : IDriverService 
{ 
    private static ChromeDriverService instance; 

    private readonly Thread _thread; 
    private readonly ConcurrentQueue<Action> _actions = new ConcurrentQueue<Action>(); 
    private volatile bool _running; 

    private ChromeDriverService() 
    { 
     _thread = new Thread(); 
     _thread.Start();    
    } 

    public static IDriverService Instance() 
    { 
     if (instance == null) 
      instance = new ChromeDriverService(); 
     return instance; 
    } 

    // This will run on the "target" _thread 
    public void StartDriverService() 
    { 
     while (true) 
     { 
      Action action; 
      if (_actions.TryDequeue(out action)) 
      { 
       try 
       { 
        action(); 
       } 
       catch (Exception ex) { // Handle } 
      } 
      else 
      { 
       if (!_running && _actions.IsEmpty) 
        return; 
      } 
     } 
    } 

    public void StopDriverService() 
    { 
     _running = false; 

     // IMPORTANT: Finish the logic here - we have a chance for race conditions. Dequeuing before the 
     // last action runs for example. This is primative, but you will have to take care of this. 
     while (!_actions.IsEmpty) 
     { 
      // Do stuff. 
     } 
    } 

    // Called from some other thread. 
    public void PerformDriverAction(Action action) 
    { 
     if (_running) 
      _actions.Enqueue(action); 
    } 
} 

これは原始的な例であると私は実行またはこれをコンパイルしようとしていません(私は私の電話にいます)。

実際、とは何もしていません。ChromeDriverです。このクラスは、そのようなオブジェクトで作業するために簡単に編集できます。

こちらがお役に立てば幸いです。

関連する問題