RichTextBox - InvalidOperationException:调用线程必须是STA

时间:2013-04-24 14:26:00

标签: c# wpf ajax multithreading richtextbox

我尝试使用MSDN中的这个Converting between RTF and HTML库将一些RTF文本转换为HTML。我的设置的主旨是从JavaScript到C#处理程序的AJAX调用,它调用此MarkupConverter库来进行转换,然后回写HTML。

这是我的JavaScript:

$.ajax({
   type: "POST",
   url: "MyHandler.ashx",
   data: richTextData,
   success: function (html) {
            alert('success, html: ' + html);
   },
   error: function (msg) {
            alert("error: " + msg);
   }
});

来自我的处理程序的代码,这也非常简单:

public void ProcessRequest(HttpContext context)
{
   if (context.Request.Form.Count > 0)
   {
      string rtf = context.Request.Form[0];
      string html = "";
      if (rtf != "")
      {
         markupConverter = new MarkupConverter.MarkupConverter();
         html = markupConverter.ConvertRtfToHtml(rtf);
      }
      if (html != "")
      {
         context.Response.ContentType = "text/html";
         context.Response.Write(html);
      }
      else
      {
         context.Response.ContentType = "text/plain";
         context.Response.Write("Error from RTF2HTML");
      }
   }
}

问题是,每次运行时都会抛出异常,因为RichTextBox控件是在后台线程上创建的:

  

[InvalidOperationException:调用线程必须是STA,因为   许多UI组件都需要这个。]
  System.Windows.Input.InputManager..ctor()+11032206
  System.Windows.Input.InputManager.GetCurrentInputManagerImpl()+125
  System.Windows.Input.KeyboardNavigation..ctor()+ 185   System.Windows.FrameworkElement.EnsureFrameworkServices()+ 109 ch   System.Windows.FrameworkElement..ctor()+504
  System.Windows.Controls.Control..ctor()+87
  System.Windows.Controls.RichTextBox..ctor(FlowDocument document)+56
  MarkupConverter.RtfToHtmlConverter.ConvertRtfToXaml(String rtfText)   +67 MarkupConverter.RtfToHtmlConverter.ConvertRtfToHtml(String rtfText)+23 MyHandler.ProcessRequest(HttpContext context)+416

我想也许是因为AJAX调用是异步的,调用会放在后台线程上。所以我改成了这个:

var postText = $.ajax({
   type: "POST",
   url: "RTF2HTML.ashx",
   data: textData,
   async: false
}).responseText;
alert(postText);

但是当我在我的处理程序中检查当前线程时仍然是这样:

context.Response.Write("thread: " + System.Threading.Thread.CurrentThread.GetApartmentState().ToString());

它仍然返回MTA。

有没有办法挂钩主STA线程,还是我必须创建一个新线程并指定STA?如果是这种情况,我如何设置回调函数以Response.Write目前的方式返回我的HTML?

2 个答案:

答案 0 :(得分:3)

这可能有用:

How to run something in the STA thread?

也许你可以打电话给......

html = markupConverter.ConvertRtfToHtml(rtf);

...以同样的方式在另一个线程上?

string rtf;

public void ProcessRequest(HttpContext context)
{
   if (context.Request.Form.Count > 0)
   {
      rtf = context.Request.Form[0];
      string html = "";
      if (rtf != "")
      {
         Thread thread = new Thread(ConvertMarkup);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
      }
      if (html != "")
      {
         context.Response.ContentType = "text/html";
         context.Response.Write(html);
      }
      else
      {
         context.Response.ContentType = "text/plain";
         context.Response.Write("Error from RTF2HTML");
      }
   }
}

void ConvertMarkup()
{
    markupConverter = new MarkupConverter.MarkupConverter();
     html = markupConverter.ConvertRtfToHtml(rtf);
}

答案 1 :(得分:0)

    using System.Threading; 

    Thread t = new Thread(new ThreadStart(ProcessRequest)); 

    // Make sure to set the apartment state BEFORE starting the thread. 
    t.ApartmentState = ApartmentState.STA; 
    t.Start(); 

    public void ProcessRequest(HttpContext context)
    {
       if (context.Request.Form.Count > 0)
       {
        string rtf = context.Request.Form[0];
        string html = "";
        if (rtf != "")
        {
           markupConverter = new MarkupConverter.MarkupConverter();
           html = markupConverter.ConvertRtfToHtml(rtf);
        }
        if (html != "")
        {
           context.Response.ContentType = "text/html";
           context.Response.Write(html);
        }
        else
        {
           context.Response.ContentType = "text/plain";
           context.Response.Write("Error from RTF2HTML");
        }
     }
  }