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.
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.
精彩评论