2016-03-03 46 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)在一个单独的线程。