2016-03-03 44 views
0

所以我一直堅持這一段時間。 (Forms應用程序)C#如何在後臺線程中運行此代碼?

我希望在「背景」中運行它。 我通常用「搜索按鈕」調用它。

到目前爲止,我讀過你不能在另一個線程訪問UI的東西?那麼我怎樣才能解決這個問題,並在加載結果並將它們轉換爲按鈕時使用戶界面可訪問? 對於剛剛開始使用C#的人來說,是否有任何簡單的方法可以做到這一點?下面

代碼:

private void Search_Video_Youtube(string page) 
    { 
     YouTubeService youtube = new YouTubeService(new BaseClientService.Initializer() 
     { 
      ApplicationName = this.GetType().ToString(), 
      ApiKey = "*MyApiKeyGoesHere*", 
     }); 

     var listRequest = youtube.Search.List("snippet"); 
     listRequest.Q = Youtube_SearchVideo_Box.Text; 
     listRequest.MaxResults = 50; 
     listRequest.Type = "video"; 
     listRequest.PageToken = nextPageToken; 
     video_results_vids = video_results_vids + 50; 

     var resp = listRequest.Execute(); 
     List<string> videos = new List<string>(); 
     foreach (SearchResult result in resp.Items) 
     { 
      switch (result.Id.Kind) 
      { 
       case "youtube#video": 
        PictureBox picturebox = new PictureBox(); 
        picturebox.Height = 100; 
        picturebox.Width = 100; 
        picturebox.BorderStyle = BorderStyle.None; 
        picturebox.SizeMode = PictureBoxSizeMode.StretchImage;   
        string template2 = "http://i3.ytimg.com/vi/{0}{1}"; 
        string data2 = result.Id.VideoId.ToString(); 
        string quality2 = "/default.jpg"; 
        string messageB = string.Format(template2, data2, quality2); 

        var request = WebRequest.Create(messageB); 
        using (var response = request.GetResponse()) 
        using (var stream = response.GetResponseStream()) 
        { 
         picturebox.Image = Bitmap.FromStream(stream); 
        } 
        flowLayoutPanel1.Controls.Add(picturebox); 


        listnumber += 1; 
        Button button = new Button(); 

        button.Text = listnumber.ToString() + " " + result.Snippet.Title.ToString(); 
        button.Tag = result.Id.VideoId; 
        button.TextImageRelation = TextImageRelation.ImageBeforeText; 
        button.FlatStyle = FlatStyle.Flat; 
        button.ForeColor = Color.LightSteelBlue; 
        button.BackColor = Color.SteelBlue; 
        button.Width = (flowLayoutPanel1.Width - 150); 
        button.TextAlign = ContentAlignment.MiddleLeft;       
        button.Height = 100; 
        button.Font = new Font(button.Font.FontFamily, 10); 
        button.Click += (s, e) => { 
         Youtube_video_Player_hider.Visible = false; 
         var a = result.Id.VideoId; 
         string template = "https://www.youtube.com/v/{0}{1}"; 
         string data = a.ToString(); 
         string quality = Video_Quality; 
         string messagea = string.Format(template, data, quality); 
         axShockwaveFlash1.Movie = messagea; 
         axShockwaveFlash1.Play(); 
        }; 
        flowLayoutPanel1.Controls.Add(button); 

        break; 
      } 
     } 
     nextPageToken = resp.NextPageToken; 
     toolStripStatusLabel1.Text = "Status : Idle"; 
     toolStripStatusLabel2.Text = "Results : " + video_results_vids; 
    } 

任何幫助是值得歡迎的,但請詳細解釋一下,因爲我很新的C#,但我有一個基本的編程知識。 編輯:謝謝Jeroen van langen(下面的答案)我找到了答案。如果你看到任何我可以做得更好,隨時指出它,我在這裏學習:))

編輯: 當前的代碼是現在:

// At using Stuff 
using ExtensionMethods; 

    private void Search_Video_Youtube(string page) 
    { 
     ThreadPool.QueueUserWorkItem(new WaitCallback((state) => 
     { 
      YouTubeService youtube = new YouTubeService(new BaseClientService.Initializer() 
      { 
       ApplicationName = this.GetType().ToString(), 
       ApiKey = "ThisIsTheApiKeyYouTubeWantsForAnyoneWondering", 
      }); 

      var listRequest = youtube.Search.List("snippet"); 
      listRequest.Q = Youtube_SearchVideo_Box.Text; 
      listRequest.MaxResults = 50; 
      listRequest.Type = "video"; 
      listRequest.PageToken = nextPageToken; 
      video_results_vids = video_results_vids + 50; 

      var resp = listRequest.Execute(); 
      List<string> videos = new List<string>(); 
      Parallel.ForEach(resp.Items, (SearchResult result) => 
      { 

       switch (result.Id.Kind) 
       { 
        case "youtube#video": 
         string template2 = "http://i3.ytimg.com/vi/{0}{1}"; 
         string data2 = result.Id.VideoId.ToString(); 
         string quality2 = "/default.jpg"; 
         string messageB = string.Format(template2, data2, quality2); 
         Image image; 
         var request = WebRequest.Create(messageB); 
         using (var response = request.GetResponse()) 
         using (var stream = response.GetResponseStream()) 
         { 
          image = Bitmap.FromStream(stream); 
         } 


         listnumber += 1; 

         this.Invoke(() => 
         { 
          PictureBox picturebox = new PictureBox(); 
          picturebox.Height = 100; 
          picturebox.Width = 100; 
          picturebox.Image = image; 
          picturebox.BorderStyle = BorderStyle.None; 
          picturebox.SizeMode = PictureBoxSizeMode.StretchImage; 

          flowLayoutPanel1.Controls.Add(picturebox); 

          Button button = new Button(); 

          button.Text = listnumber.ToString() + " " + result.Snippet.Title.ToString(); 
          button.Tag = result.Id.VideoId; 
          button.TextImageRelation = TextImageRelation.ImageBeforeText; 
          button.FlatStyle = FlatStyle.Flat; 
          button.ForeColor = Color.LightSteelBlue; 
          button.BackColor = Color.SteelBlue; 
          button.Width = (flowLayoutPanel1.Width - 150); 
          button.TextAlign = ContentAlignment.MiddleLeft; 
          button.Height = 100; 
          button.Font = new Font(button.Font.FontFamily, 10); 
          button.Click += (s, e) => 
          { 
           Youtube_video_Player_hider.Visible = false; 
           var a = result.Id.VideoId; 
           string template = "https://www.youtube.com/v/{0}{1}"; 
           string data = a.ToString(); 
           string quality = Video_Quality; 
           string messagea = string.Format(template, data, quality); 
           axShockwaveFlash1.Movie = messagea; 
           axShockwaveFlash1.Play(); 
          }; 
          flowLayoutPanel1.Controls.Add(button); 
         }); 
         break; 
       } 

       nextPageToken = resp.NextPageToken; 

       this.Invoke(() => 
       { 
        toolStripStatusLabel1.Text = "Status : Idle"; 
        toolStripStatusLabel2.Text = "Results : " + video_results_vids; 
       }); 
      }); 

     })); 
    } 

類內容:

using System; 
using System.Windows.Forms; 

namespace ExtensionMethods 
{ 
    public static class MyExtensions 
    { 
     public static void Invoke(this Control control, Action action) 
     { 
      control.Invoke((Delegate)action); 
     } 
    } 
} 
+0

那麼最耗時的部分似乎是加載50個按鈕。 我有我的代碼像http://stackoverflow.com/questions/35763971/c-sharp-net-youtube-v3-api-issue-listing-items-to-control/35764318#35764318之前,這給了它自己的問題= \。並且在GUI線程中,我認爲這就是通常正確執行的地方?到目前爲止,C#有點讓人困惑,所以對於noob問題感到抱歉。 – R593B

+0

您不能直接從另一個線程訪問由UI線程創建的對象。但是,您可以**跳轉線程,或者對UI線程執行'BeginInvoke'調用,以更新/修改其控件。很多互聯網上的例子... :-) – code4life

回答

1

你應該在一個線程中執行的 '整體' 的方法。嘗試將所有控件的創建移動到一個部分,並在GUI線程上調用該部分。最耗時將是WebRequests

僞:是這樣的:

private void Search_Video_Youtube(string page) 
{ 
    ThreadPool.QueueUserWorkItem(new WaitCallback((state) => 
    { 
     YouTubeService youtube = new YouTubeService(new BaseClientService.Initializer() 
     { 
      ApplicationName = this.GetType().ToString(), 
      ApiKey = "*MyApiKeyGoesHere*", 
     }); 

     var listRequest = youtube.Search.List("snippet"); 
     listRequest.Q = Youtube_SearchVideo_Box.Text; 
     listRequest.MaxResults = 50; 
     listRequest.Type = "video"; 
     listRequest.PageToken = nextPageToken; 
     video_results_vids = video_results_vids + 50; 

     var resp = listRequest.Execute().OfType<SearchResult>(); 
     List<string> videos = new List<string>(); 
     Parallel.Foreach(resp.Items, (result) => 
     { 

      switch (result.Id.Kind) 
      { 
       case "youtube#video": 
        string template2 = "http://i3.ytimg.com/vi/{0}{1}"; 
        string data2 = result.Id.VideoId.ToString(); 
        string quality2 = "/default.jpg"; 
        string messageB = string.Format(template2, data2, quality2); 
        Bitmap image; 
        var request = WebRequest.Create(messageB); 
        using (var response = request.GetResponse()) 
        using (var stream = response.GetResponseStream()) 
        { 
         image = Bitmap.FromStream(stream); 
        } 


        listnumber += 1; 

        this.Invoke(() => 
        { 
         PictureBox picturebox = new PictureBox(); 
         picturebox.Height = 100; 
         picturebox.Width = 100; 
         picturebox.Image = image; 
         picturebox.BorderStyle = BorderStyle.None; 
         picturebox.SizeMode = PictureBoxSizeMode.StretchImage;   

         flowLayoutPanel1.Controls.Add(picturebox); 

         Button button = new Button(); 

         button.Text = listnumber.ToString() + " " + result.Snippet.Title.ToString(); 
         button.Tag = result.Id.VideoId; 
         button.TextImageRelation = TextImageRelation.ImageBeforeText; 
         button.FlatStyle = FlatStyle.Flat; 
         button.ForeColor = Color.LightSteelBlue; 
         button.BackColor = Color.SteelBlue; 
         button.Width = (flowLayoutPanel1.Width - 150); 
         button.TextAlign = ContentAlignment.MiddleLeft;       
         button.Height = 100; 
         button.Font = new Font(button.Font.FontFamily, 10); 
         button.Click += (s, e) => { 
          Youtube_video_Player_hider.Visible = false; 
          var a = result.Id.VideoId; 
          string template = "https://www.youtube.com/v/{0}{1}"; 
          string data = a.ToString(); 
          string quality = Video_Quality; 
          string messagea = string.Format(template, data, quality);  
          axShockwaveFlash1.Movie = messagea; 
          axShockwaveFlash1.Play(); 
         }; 
         flowLayoutPanel1.Controls.Add(button); 
        }); 
        break; 
      } 

     nextPageToken = resp.NextPageToken; 

     this.Invoke(() => 
     { 
      toolStripStatusLabel1.Text = "Status : Idle"; 
      toolStripStatusLabel2.Text = "Results : " + video_results_vids; 
     }); 
    }, null); 

} 
+0

要玩這個!看起來非常有幫助,並且那麼到目前爲止我看到的並不複雜!幾分鐘後會回來! – R593B

+0

我在瀏覽器中寫了這個,所以不要判斷語法檢查。這只是一個例子。你可能會知道如何調用等。 –

+0

老實說,還不是100%,就像我說的C#新手一樣,當你的谷歌文檔已遍佈全球。 (對於舊版本的很多結果,我經常會碰到更新的使用方法(就像你在這裏做的,我看到它的非常複雜的版本,只是讓我的大腦放棄)所以,如果你有一個鏈接我可以閱讀一些關於它的適當的文檔將是不錯的 到目前爲止我已經偶然發現了一個問題:我無法訪問Switch上的result.Id.Kind(result.Id.Kind)說它不存在。 – R593B

0

創建一個委託,它需要一個類型的resp

public delegate void ListDispatcher(var resp) 

記得的說法,VAR需要與被替換確切類型的resp

現在在主類中創建一個ListDispatcher引用成員。

public ListDispatcher dispatcher; 

並在其調用列表中添加一個新方法。

dispatcher += MyNewMethod; 

定義新的方法

public void MyNewMethod(var resp){ 

//Move all your controls creation code here 

} 

通話後刪除代碼

var resp = listRequest.Execute(); 

,只是放在那裏

dispatcher(resp); 

現在可以安全地調用該Search_Video_Youtube(string page)在一個單獨的線程。