2017-02-05 3 views
1

私は、プログラムでキーワードによるYoutube検索を行い、これを行うにはYoutube APIを使用しています。検索の進行が完了したときにイベントを発生させ、YoutubeSearchCompletedEventArgsの結果をYoutubeSearchCompletedで返します。イベントの制御テキストの更新で不正なクロススレッド例外がスローされる

しかし、のコードでは、Form.csがクロススレッド違法操作例外をスローします。通常、AsyncOperation.Postメソッドを使用すると、InvalidOperationExceptionを投げてはなりません。以前はダウンロードマネージャプロジェクトで同じ方法を使用していたので、うまくいきました。だから私はなぜこれが起こるのか理解できません。このコードで

YouTube検索クラス

class YouTubeManager 
{ 
    public delegate void YoutubeSearchCompletedEventHandler(object sender, YoutubeSearchCompletedEventArgs e); 
    public event YoutubeSearchCompletedEventHandler YoutubeSearchCompleted; 
    AsyncOperation aop = AsyncOperationManager.CreateOperation(null); 

    List<YoutubeVideo> SearchByKeyword(string keyword) 
    { 
     List<YoutubeVideo> videos = new List<YoutubeVideo>(); 

     //....... 
     //...Youtube data api search codes.... 
     //....... 

     return videos; 
    } 
    public void Search(string keyword) 
    { 
     Task.Run(() => 
     { 
      List<YoutubeVideo> list = SearchByKeyword(keyword); 
      aop.Post(new System.Threading.SendOrPostCallback(delegate 
      { 
       if (YoutubeSearchCompleted != null) 
        YoutubeSearchCompleted(this, 
         new YoutubeSearchCompletedEventArgs(keyword, list); 
      }), null); 
     }); 
    } 
} 

Form.cs

public partial class Form1 : Form 
{ 
    YouTubeManager yam = new YouTubeManager(); 
    public Form1() 
    { 
     InitializeComponent(); 
     this.Load += Form1_Load; 
    } 

    void Form1_Load(object sender, EventArgs e) 
    { 
     yam.YoutubeSearchCompleted += yam_YoutubeSearchCompleted; 
     yam.Search("Blues"); 
    } 

    void yam_YoutubeSearchCompleted(object sender, YoutubeSearchCompletedEventArgs e) 
    { 
     if (e.Videos.Count < 1) return; 

     textBox1.Text = e.Videos[0].Title(); 
    } 
} 

textBox1.Text = e.Videos[0].Title();ラインはInvalidOperationExceptionをスロー。この問題を解決するにはどうすればよいですか?

注:私はInvokeメソッドを望んでいません。ちょうどAsyncOperationです。

答えて

3

多くの場合、問題はAsyncOperationがあまりにも早く作成されたために発生しています。次のように確認できます:

if (!(aop.SynchronizationContext is WindowsFormsSynchronizationContext)) 
{ 
    // Oops - we have an issue 
} 

なぜですか? AsyncOperationは、構築時にSynchronizationContext.Currentを格納します。通常は、すべてControlの派生クラス(Formを含む)がControlクラスコンストラクタ内にWindowsFormsSynchronizationContextをインストールします。

しかし、Forgm1があなたのスタートアップフォーム(たとえば、Application.Run(new Form1());の電話番号Main)であるとします。 Any instance variable initializers in the derived class are executed before the base class constructorので、一度にaop変数はControlクラスコンストラクタは、したがってWindowsFormsSynchronizationContextがインストールされていない、まだ実行されていない、(yamフィールドイニシャライザによって)初期化されるので、AsynOperationは単に実行することによってPostを実装デフォルトSynchronozationContext、で初期化されますそれは別のスレッド上にある。修正は簡単です

- 初期化子を使用していない、単にフィールド

YouTubeManager yam; 

を定義して、フォームのコンストラクタまたはLoadイベント内で初期化

yam = new YouTubeManager(); 

を移動します。

+0

解決策は問題なく動作します。手伝ってくれてありがとう。 –

関連する問題