初始化时ThreadState异常
这是一个很长的问题,所以首先是总结,
- 我的信使项目有一个 Client 类。
- 我的 Client 类有一个 Socket。
- 我使用它的 BeginReceive 方法从服务器获取消息。
- 在 BeginReceive 的异步回调中,我使用 EndReceive 获取消息。
- 当我收到消息时,我用消息本身触发 MessageReceived 事件。
- 我在消息表单中使用这个 Client 类。
- 在消息形式中,我可以通过将方法附加到 Client.MessageReceived 来获取收到的消息。
- 为此,我使用 OnMessageReceived 方法。
- 当我收到消息时,我可以将其显示在 TextBox(使用 Control.Invoke)或 MessageBox 上。
- 我还可以在 OnMessageReceived 中向 TabControl 添加新选项卡。
- 当我尝试初始化 WebBrowser 控件时,出现 ThreadStateException。
- 我用来显示消息的控件派生自 WebBrowser 控件,因此我需要它。
- Threading.Thread.CurrentThread.ThreadState 是“背景”。
我认为您不需要详细信息,但您可以找到我首先打算在下面发布的详细问题。
非常感谢。
我正在使用 Net.Socket 的异步方法开发一个信使项目(服务器是 Windows 服务,客户端是 Windows 窗体应用程序)。 我在 Socket.BeginReceive 的回调中触发 Client 的 MessageReceived 事件; 直到这里,一切都是我希望的样子。
我在我的表单中使用 MessageReceived 事件(两个人互相写信的事件),我可以使用 Control.Invoke 方法(如果需要)对 UI 执行任何我想要的操作,但有一个恼人的异常。
我在表单中设置了选项卡式对话,因此当消息到达时,我会检查是否与发件人有打开的对话(选项卡)。如果是,我选择该选项卡并显示消息。如果不是,我将创建一个新的 ConversationTab。
现在,如果这是一个很长的问题,或者我无法充分解释自己,我很抱歉。英语不是我的母语,这是我在 Stack Overflow 上的第一个问题。 因此,这里是 ConversationTab:
public class ConversationTab : TabPage
{
public User Friend { get; private set; }
public MessageBrowser MessageBrowser { get; private set; }
public ConversationTab(User friend) : base(friend.DisplayName)
{
Friend = friend;
MessageBrowser = new MessageBrowser();
Controls.Add(MessageBrowser);
MessageBrowser.Dock = DockStyle.Fill;
}
}
MessageBrowser 派生自 WebBrowser,我使用它的原因是因为我无法使用 RichTextBox 对“每条消息”应用自定义样式(颜色、字体、大小)。 RichTextBox.SelectedColor 并不总是有效,或者我无法使其按预期工作。 MessageBrowser 让我使用 CSS 来代替。偏离主题了吗?对不起。
以下是当 MessageReceived 事件触发时我调用的 NewConversation 方法:
public void NewConversation(User friend)
{
ConversationTab tab = Conversations.FirstOrDefault(c => c.Friend.Id == friend.Id);
if (tab != null)
ActiveConversation = tab;
else
{
tab = new ConversationTab(friend);
// add tab to TabControl
}
// bla
}
“Conversations”获取 TabControl 的选项卡页,“ActiveConversation”获取或设置 TabControl 的 SelectedTab 属性。 我创建这些属性的目的主要是内部的线程安全逻辑。
所以问题是:它在上面代码的“tab = new ConversationTab(friend)”部分抛出ThreadStateException。它是第一段代码的“MessageBrowser = new MessageBrowser()”部分,也是MessageBrowser的构造函数。我之所以没有提供MessageBrowser的构造函数代码,是因为在执行任何行内部代码之前都会抛出异常(这是关于WebBrowser的构造函数,当我尝试初始化WebBrowser时也会遇到此异常。) 实际上我什至没有得到异常,应用程序只是在那里关闭而不通知我任何事情。当我尝试在“监视”窗口中的 ConversationTab 构造函数上调用“MessageBrowser = new MessageBrowser()”时,我看到了异常。
我对使用线程和异步方法有点陌生。 MSDN 说:
ThreadStateException 由由于线程的当前状态而无法执行请求的操作的方法引发。
就我而言,线程的状态是“背景”。 我不知道我做错了什么。
如果您阅读了整篇文章,我们将非常感谢;如果您能提供帮助,我们将更加感谢您。
It has been a long question, so here is the summary first,
- I have a Client class for my messenger project.
- My Client class has a Socket.
- I use its BeginReceive method to get messages from server.
- In async callback of BeginReceive, I get the message using EndReceive.
- When I get the message, I fire the MessageReceived event with message itself.
- I use this Client class in my message form.
- In message form, I can get the received message by attaching a method to Client.MessageReceived.
- I use OnMessageReceived method for this purpose.
- When I get the message, I can show it on a TextBox (using Control.Invoke) or MessageBox.
- I can also add a new tab to my TabControl in OnMessageReceived.
- When I try to initialize a WebBrowser control, I get ThreadStateException.
- The control I use to display messages derives from WebBrowser control, so I need it.
- Threading.Thread.CurrentThread.ThreadState is "Background".
I don't think you'll need the details but you can find the detailed question I first intented to post below.
Many thanks.
I'm working on a messenger project (Server is a Windows Service and Client is a Windows Forms Application) using Net.Socket's async methods.
I fire Client's MessageReceived event in callback of Socket.BeginReceive;
Everything is how I want them to be until here.
I use MessageReceived event in my form (the one that two people writes to each other) I can do anything I want to the UI using Control.Invoke method (if required) with one annoying exception.
I have tabbed conversations in the form so when a message arrives, I check if there is an open conversation (tab) with the sender. If yes, I select that tab and display the message. If no, I create a new ConversationTab.
Now, I'm sorry if it's being a long question than it should be or if I can't explain myself sufficently. English is not my first language and this is my first question in Stack Overflow.
So, here is the ConversationTab:
public class ConversationTab : TabPage
{
public User Friend { get; private set; }
public MessageBrowser MessageBrowser { get; private set; }
public ConversationTab(User friend) : base(friend.DisplayName)
{
Friend = friend;
MessageBrowser = new MessageBrowser();
Controls.Add(MessageBrowser);
MessageBrowser.Dock = DockStyle.Fill;
}
}
MessageBrowser derives from WebBrowser and the reason I use this is because I could not apply custom styles (color, font, size) 'per message' using RichTextBox. RichTextBox.SelectedColor doesn't always work or I couldn't make it work as intended. MessageBrowser let's me use CSS instead. Wandering off of the subject? Sorry.
Here is the NewConversation method I call when MessageReceived event fires:
public void NewConversation(User friend)
{
ConversationTab tab = Conversations.FirstOrDefault(c => c.Friend.Id == friend.Id);
if (tab != null)
ActiveConversation = tab;
else
{
tab = new ConversationTab(friend);
// add tab to TabControl
}
// bla
}
"Conversations" gets the tab pages of the TabControl and "ActiveConversation" gets or sets the SelectedTab property of the TabControl.
My point in creating these properties are mostly thread-safety logic inside.
So the question: It's throwing ThreadStateException in "tab = new ConversationTab(friend)" part of the above code. It is the "MessageBrowser = new MessageBrowser()" part of the first code and the constructor of MessageBrowser. The reason of why I didn't provide MessageBrowser's constructor code is because the exception is thrown before any line of inner code gets executed (It is about WebBrowser's constructor, I get this exception when I try to initalize a WebBrowser, too.)
Actually I don't even get an exception, the application just closes there without notifying me about anything. I saw the exception when I try to call "MessageBrowser = new MessageBrowser()" on ConversationTab's constructor in Watch window.
I'm kind of new to using threads and asynchronous methods.
MSDN says:
ThreadStateException is thrown by methods that cannot perform the requested operation due to the current state of a thread.
In my case, the thread's state is "Background".
I have no clue about what am I doing wrong.
Thank you very much if you read the whole thing and thank you much more if you can help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这似乎与.NET 中使用COM(Web 浏览器控件使用COM)有关,其中线程单元需要设置为
STA
。尝试将
[STAThread]
添加到您的入口点。请查看此。
This seems to be related to using COM (web browser control uses COM) in .NET where thread apartment needs to be set to
STA
.Try adding
[STAThread]
to your entry point.Have a look at this.