多线程C#Windows窗体

多线程C#Windows窗体

问题描述:

所以我试图在Windows窗体项目中实现多线程.我知道一种执行此操作的方法,方法是为要单独运行的方法创建一个新线程,如下所示:

So I am trying to implement multi-threading in my windows forms project. I know of one way to do this, by creating a new thread for the methods you want to run separately like this:

Thread t = new Thread(new ThreadStart(methodName));
t.Start();

然后调用从创建该线程的线程以外的线程访问"的每个对象.像这样:

And then invoking each object that is "Accessed from a thread other than the thread it was created on." like this:

this.Invoke(new MethodInvoker(delegate()
{
this.Object = "whatever";
 }));

唯一的问题是,我的程序长数千行,而且我一直在进行引用.因此,将方法调用程序放在我想在另一个线程中更改的每个小事情周围似乎效率极低,我确定有更好的方法,但是我似乎无法在线找到它,所以我想知道为什么不问你们.

The only problem with this is, my program is several thousand lines long, and I make the references all the time. So putting a method invoker around every little thing I want to change in another thread seems horribly inefficient and Im sure there is a better way but I cant seem to find it online so I figured why not ask you guys.

如果在线程外引用对象,该方法的开头是否可以自动委派对象?因为如果没有其他方法,我的代码可能会变成真正的混乱且难以阅读. :(

Is there something I can say at the beginning of the method that will automatically delegate objects if they are referenced outside the thread? Because if there isnt another way, my code is probably going to turn out real messy and hard to read. :(

这是代码的一大块,也许会使它更清晰一些:

Here is a larger chunk of the code, maybe it will make this a bit clearer:

foreach (var lines in serversToRunTextBox.Lines)
{
    manipulationTextBox.Text = lines;
    string line = manipulationTextBox.Text;
    string scriptWithWild = actualScriptTextBox.Text.Replace(wildCard.ToString(), line);
    shellStream.WriteLine(scriptWithWild);
    Thread.Sleep(100);
    client.RunCommand(scriptWithWild);
    //MessageBox.Show(scriptWithWild);
    Thread.Sleep(2500);

    reply = shellStream.Read();
    if (reply.Contains("denied"))
    {
        MessageBox.Show("You must have sudo access for this command", "No Sudo", MessageBoxButtons.OK, MessageBoxIcon.Hand);
    }
    else
    {
       this.Invoke(new MethodInvoker(delegate()
       {
           actualResultsTextBox.AppendText(reply + "\n \n");
       }));

一种解决方法是利用C#5.0附带的async/await功能.

One way to deal with this is to leverage the async/await feature which was shipped with C# 5.0.

private async Task DoSomethingAsync()
{
    //Some code
    string text = await GetSomeTextAsync(somrParam);
    statusTextBox.Text = text;//Will execute in captured context
    //Some more code
}

关键字后的

代码将在捕获的上下文中执行.因此,如果您已在UI线程中调用DoSomethingAsync,则statusTextBox.Text = text;将在UI线程本身中执行.因此,您无需调用this.Invoke.结果是不再有丑陋的代码!".

Code after the await keyword will execute in the captured context. So if you've called the DoSomethingAsync in UI thread, statusTextBox.Text = text; will execute in UI thread itself. So you don't need to call this.Invoke. And the result is "No more ugly code!!".

如果您不熟悉异步/等待您可以从这里开始此处

If you're not familiar with async/await you can start here and here