生成代码在Windows窗体中无法正常运行

时间:2017-12-18 20:42:58

标签: c# multithreading windows-forms-designer

我在Windows窗体应用程序中创建了一个程序,以获取我需要的代码。我想将其设置为在按下提交按钮时不阻止UI

我使用了这些代码。但是我得到 invalidoperationexception 是未处理的异常..

我试过

void Generate()
{
    textBox2.Text = "";

    string[] sss = textBox1.Text.Split('\n');

    textBox2.Text = "VERSION BUILD=8820413 RECORDER=FX" + Environment.NewLine +
    "SET !ERRORIGNORE YES" + Environment.NewLine +

       "SET !TIMEOUT_TAG 3" + Environment.NewLine +
        "SET !TIMEOUT_STEP 3" + Environment.NewLine +
      "SET !TIMEOUT_PAGE 7" + Environment.NewLine +
        "SET !REPLAYSPEED FAST" + Environment.NewLine;
    string[] emails = textBox3.Text.Split('\n');

    // label2.Text = emails.Length.ToString();
    //foreach (string email in emails)
    for (int i = 0; i < Convert.ToInt32(textBox5.Text); i++)
    {
        textBox2.Text += "TAB T=1" + Environment.NewLine + "CLEAR" + Environment.NewLine +
            "URL GOTO=https://signin.ebay.com/ws/eBayISAPI.dll?SignIn&lgout=" + Environment.NewLine +
            "WAIT SECONDS=1" + Environment.NewLine +
            "TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:SIGNINFORM ATTR=ID:SUBMIT" + Environment.NewLine +
            "SET !ENCRYPTION NO" + Environment.NewLine +
            "TAG POS=1 TYPE=INPUT:PASSWORD FORM=ID:SIGNINFORM ATTR=ID:PASS CONTENT=Maths7524" + Environment.NewLine +
            "TAG POS=1 TYPE=INPUT:TEXT FORM=ID:SIGNINFORM ATTR=ID:USERID CONTENT=" + emails[i] + Environment.NewLine +
            "TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:SignInForm ATTR=ID:sgnBt" + Environment.NewLine + "WAIT SECONDS=7" + Environment.NewLine;
        foreach (string item in sss)
        {

            textBox2.Text += "URL GOTO=www.ebay.com/itm/" + item + Environment.NewLine + "WAIT SECONDS=1" + Environment.NewLine + "TAG POS=1 TYPE=SPAN ATTR=ID:watchLabel" + Environment.NewLine + "TAG POS=1 TYPE=A ATTR=TXT:Watch" + Environment.NewLine + "WAIT SECONDS=1" + Environment.NewLine + Environment.NewLine;
        }
    }
}

这是按钮点击事件

private void button1_Click(object sender, EventArgs e)
{
    //Generate();

    Thread thead = new Thread(() =>
    {
        Generate();
        label6.Text = "Done.";
    });
    thead.Start();

    label6.Text = "Generating Code.. Please wait....";
}

1 个答案:

答案 0 :(得分:2)

只有UI线程才能更新UI。在另一个线程中运行耗时的I / O操作或长时间运行的计算是有意义的;但是,运行一个基本上只更新另一个线程中的文本框的方法是没有意义的。此方法必须在文本框上调用Invoke,使文本框操作再次在UI线程上运行。

只需在点击事件中正常运行此方法。

您可以使用StringBuilder并仅分配到文本框一次来加快方法的速度:

string[] sss = textBox1.Text.Split('\n');
string[] emails = textBox3.Text.Split('\n');

var sb = new StringBuilder();
sb.AppendLine("VERSION BUILD=8820413 RECORDER=FX");
sb.AppendLine("SET !ERRORIGNORE YES");
sb.AppendLine("SET !TIMEOUT_TAG 3");
sb.AppendLine("SET !TIMEOUT_STEP 3");
sb.AppendLine("SET !TIMEOUT_PAGE 7");
sb.AppendLine("SET !REPLAYSPEED FAST");

for (int i = 0; i < Convert.ToInt32(textBox5.Text); i++)
{
    sb.AppendLine("TAB T=1").AppendLine("CLEAR");
    sb.AppendLine("URL GOTO=https://signin.ebay.com/ws/eBayISAPI.dll?SignIn&lgout=");
    sb.AppendLine("WAIT SECONDS=1");
    sb.AppendLine("TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:SIGNINFORM ATTR=ID:SUBMIT");
    sb.AppendLine("SET !ENCRYPTION NO");
    sb.AppendLine("TAG POS=1 TYPE=INPUT:PASSWORD FORM=ID:SIGNINFORM ATTR=ID:PASS CONTENT=Maths7524");
    sb.Append("TAG POS=1 TYPE=INPUT:TEXT FORM=ID:SIGNINFORM ATTR=ID:USERID CONTENT=").AppendLine(emails[i]);
    sb.AppendLine("TAG POS=1 TYPE=INPUT:SUBMIT FORM=ID:SignInForm ATTR=ID:sgnBt");
    sb.AppendLine("WAIT SECONDS=7");
    foreach (string item in sss)
    {
        sb.Append("URL GOTO=www.ebay.com/itm/").AppendLine(item);
        sb.AppendLine("WAIT SECONDS=1").AppendLine("TAG POS=1 TYPE=SPAN ATTR=ID:watchLabel");
        sb.AppendLine("TAG POS=1 TYPE=A ATTR=TXT:Watch").AppendLine("WAIT SECONDS=1").AppendLine();
    }
}
textBox2.Text = sb.ToString();

字符串是不可变的。重复连接字符串效率不高,因为每次都会创建一个新的字符串对象,并将旧字符串对象的内容复制到新字符串+新文本。另一方面,StringBuilder与内部字符串缓冲区一起使用,该缓冲区可以增长直到达到其最大容量。然后它创建一个更大的缓冲区并将旧黄油的文本复制到新缓冲区。这个新缓冲区有足够的可用空间,因此在必须执行新的调整大小操作之前,可以附加许多新的文本片段。

重复分配到同一文本框非常耗时,因为文本框也会触发事件。只分配一次最终文本,可以进一步加快速度。

我认为,像这样,没有多线程就足够快。如果它不应该,我会创建一个只创建字符串并使用它来创建可以等待的任务的方法。请注意,await 会阻止用户界面。

private string Generate()
{
    var sb = new StringBuilder();
    //TODO: Create the text with a StringBuilder as shown above.
    return sb.ToString();
}

private async Task<string> GenerateAsync()
{
    return await Task.Run(() => Generate());
}

// Don't forgat the async keyword in button1_Click!
private async void button1_Click(object sender, EventArgs e)
{
    label6.Text = "Generating Code.. Please wait....";

    string text = await GenerateAsync();

    textBox2.Text = text;
    label6.Text = "Done.";
}