C#如何在后台线程中运行此代码?
所以我一直坚持这一段时间。 (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);
}
}
}
你应该在一个线程中执行的 '整体' 的方法。尝试将所有控件的创建移动到一个部分,并在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);
}
要玩这个!看起来非常有帮助,并且那么到目前为止我看到的并不复杂!几分钟后会回来! – R593B
我在浏览器中写了这个,所以不要判断语法检查。这只是一个例子。你可能会知道如何调用等。 –
老实说,还不是100%,就像我说的C#新手一样,当你的谷歌文档已遍布全球。 (对于旧版本的很多结果,我经常会碰到更新的使用方法(就像你在这里做的,我看到它的非常复杂的版本,只是让我的大脑放弃)所以,如果你有一个链接我可以阅读一些关于它的适当的文档将是不错的 到目前为止我已经偶然发现了一个问题:我无法访问Switch上的result.Id.Kind(result.Id.Kind)说它不存在。 – R593B
创建一个委托,它需要一个类型的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)
在一个单独的线程。
那么最耗时的部分似乎是加载50个按钮。 我有我的代码像http://*.com/questions/35763971/c-sharp-net-youtube-v3-api-issue-listing-items-to-control/35764318#35764318之前,这给了它自己的问题= \。并且在GUI线程中,我认为这就是通常正确执行的地方?到目前为止,C#有点让人困惑,所以对于noob问题感到抱歉。 – R593B
您不能直接从另一个线程访问由UI线程创建的对象。但是,您可以**跳转线程,或者对UI线程执行'BeginInvoke'调用,以更新/修改其控件。很多互联网上的例子... :-) – code4life