2013-04-24 113 views
1

我试图使用MSDN的Converting between RTF and HTML库将一些RTF文本转换为HTML。我的设置的jist是从JavaScript到C#处理程序的AJAX调用,它调用此MarkupConverter库进行转换,然后写回HTML。RichTextBox - InvalidOperationException:调用线程必须是STA

这里是我的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:调用threa d必须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
System.Windows.FrameworkElement..ctor()504
System.Windows.Controls.Control..ctor ()+87
System.Windows.Controls.RichTextBox..ctor(FlowDocument document)+56
MarkupConverter.RtfToHtmlConv erter.ConvertRtfToXaml(字符串rtfText) +67 MarkupConverter.RtfToHtmlConverter.ConvertRtfToHtml(字符串rtfText)+23 MyHandler.ProcessRequest(HttpContext的背景下)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?如果是这样的话,我如何设置回调函数来返回我目前使用的HTML Response.Write

回答

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); 
} 
+0

执行'thread.Join()'后会执行等待,以便在'ConvertMarkup()'完成后'if(html!='')'行不执行? – lhan 2013-04-24 15:13:10

+0

显然它!工作!谢谢! – lhan 2013-04-24 15:15:53

+2

没问题,乐于帮忙! thread.Join自己发信号给调用线程等待,直到线程执行完成...简单但是完成工作。 – Henners 2013-04-24 15:24:28

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"); 
     } 
    } 
    } 
+0

虽然,很明显这将创建一个新的线程,但没有办法绕过它。有很多谷歌搜索,你可以做,看看为什么这是需要用户界面。 – Jeff 2013-04-24 15:04:42

+0

谢谢。一个问题 - 新的ThreadStart行上的语法错误,“ProcessRequest的重载没有匹配委托”System.Threading.ThreadStart“”。有任何想法吗? – lhan 2013-04-24 15:06:31

+0

是的......对不起我的坏处。为你的函数松开HttpContext参数。你不能传递函数一个参数。 – Jeff 2013-04-24 15:16:30

相关问题