在多线程应用程序中访问RichTextBox会导致OutOfMemoryException

时间:2014-12-09 00:05:23

标签: c# multithreading winforms msmq

我可能只是做错了。我目前正在使用MSMQ和Webservices。我想了解MSMQ是如何运作的,所以我找到了一个贷款经纪人的学校例子。

总而言之,我需要能够对我的系统进行压力测试,因此我希望能够制作100条消息并通过我的消息系统发送它们。我想从Windows窗体应用程序中做到这一点,但这就是问题所在。我的表格看起来像这样:

main form

在左侧,您会看到一个自定义控件,在右侧,我的“控制台”窗口会告诉我发生了什么。当我按下发送按钮时,它应该使用它上面的字段中给出的数据来发送消息。但是当我按下发送按钮时,程序会冻结一段时间,然后点击OutOfMemoryException。这是Send方法:

private void Send(List<SimpleRequest.LoanRequest> list)
{
    int quantity = int.Parse(numericQuantity.Value.ToString());
    int delay = int.Parse(numericDelay.Value.ToString());

    if (list.Count == 1)
    {
        for (int threadnumber = 0; threadnumber < quantity; threadnumber++)
        {
            Task.Factory.StartNew(() => RequestLoanQuote(threadnumber, list[0]));
            if (delay > 0)
            {
                Thread.Sleep(delay);
            }
        }
    }
    else
    {
        for (int threadnumber = 0; threadnumber < quantity; threadnumber++)
        {
            Task.Factory.StartNew(() => RequestLoanQuote(threadnumber, list[threadnumber]));
            if (delay > 0)
            {
                Thread.Sleep(delay);
            }
        }
    }
}

以下是RequestLoanQuote方法正在调用的Send方法:

private void RequestLoanQuote(object state, SimpleRequest.LoanRequest loanRequest)
{
    try
    {
        if (console.InvokeRequired)
        {
            SetText("Sending: " + loanRequest.SSN + "\n");
        }

        StringBuilder sb = new StringBuilder();
        var threadnumber = (int)state;
        using (var client = new LoanBrokerWS.LoanBrokerWSClient())
        {
            Utility_Tool.LoanBrokerWS.LoanQuote response = client.GetLoanQuote(loanRequest.SSN, loanRequest.LoanAmount, loanRequest.LoanDuration);
            sb.Append(response.SSNk__BackingField + " returned: ");
            sb.Append(response.interestRatek__BackingField + " | ");
            sb.Append(response.BankNamek__BackingField + "\n");
            SetText(sb.ToString());
        }
    }
    catch (Exception e)
    {
        SetText(e.Message + "\n");
    }
}

最后,SetText方法:

private void SetText(String msg)
{
    if (this.console.InvokeRequired)
    {
        SetTextCallback d = new SetTextCallback(SetText);
        this.Invoke(d, new object[] { msg });
    }
    else
    {
        this.console.Text += msg;
    }
}

因此Send方法调用调用RequestLoanQuote方法的SetText方法。我无法弄清楚我哪里出错但它可能是一个僵局。

1 个答案:

答案 0 :(得分:1)

尝试使用BeginInvokeAppendText,如下所示:

    public static void SetText(this RichTextBox textBox, string msg)
    {
        Action append = () => textBox.AppendText(msg);

        if (textBox.InvokeRequired)
            textBox.BeginInvoke(append);
        else
            append();
    }