C# 使用非主UI线程显示表单消息
我有一个项目,没有使用任何表单/按钮或类似的东西,它与Websocket连接,并使用异步方法接收一些消息(在我自己创建的表单上),这些消息应该显示在屏幕的右上角 但是,如果websocket没有说它必须停止,则此消息可能会不时(2或3分钟)出现在屏幕上。这个消息可以足够大,为了让它看起来更好,我让我的消息以多种形式出现 这会给人一种通知的印象。因此,与websocket连接并接收消息async的类使用作为控制器的线程调用另一个类。控制器的目的是不时地在各种新的form()通知中显示该消息,如果websocket不返回任何消息,则显然不会这样做 但是当我调用form.show时,程序停止工作。 我已经环顾了stackoverflow,但我发现的想法似乎不起作用 有人说我应该使用invoke,但它不断给出错误的说法 “在创建窗口句柄之前,无法对控件调用Invoke或BeginInvoke”,尝试这样解决:但它不起作用 有人说我应该使用.showDialog而不是.show,但它似乎不太好,因为它等待窗口关闭以终止该方法,正如我所说的,我需要同时打开多个通知 有人说表单是用.show打开的,但它只打开了很短的一段时间。但我没有注意到情况是否如此,即使如此,我也无法解决它。好吧,重要的是我被卡住了,我不知道该怎么做 编辑代码:C# 使用非主UI线程显示表单消息,c#,multithreading,forms,websocket,notifications,C#,Multithreading,Forms,Websocket,Notifications,我有一个项目,没有使用任何表单/按钮或类似的东西,它与Websocket连接,并使用异步方法接收一些消息(在我自己创建的表单上),这些消息应该显示在屏幕的右上角 但是,如果websocket没有说它必须停止,则此消息可能会不时(2或3分钟)出现在屏幕上。这个消息可以足够大,为了让它看起来更好,我让我的消息以多种形式出现 这会给人一种通知的印象。因此,与websocket连接并接收消息async的类使用作为控制器的线程调用另一个类。控制器的目的是不时地在各种新的form()通知中显示该消息,如果w
//Main
Application.Run(new SocketService());
//SocketService class
public SocketService()
{
alerta = null;
while (true)
{
try
{
//Console.WriteLine("Nome do Usúario:" + Environment.UserName);
Thread.Sleep(2000);
Connect("ws://192.168.120.38:9091").Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public static async Task Connect(string uri)
{
ClientWebSocket webSocket = null;
try
{
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);
await Login(webSocket);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (webSocket != null)
webSocket.Dispose();
lock (consoleLock)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("WebSocket closed.");
Console.ResetColor();
}
}
}
private static async Task Login(ClientWebSocket webSocket)
{
ArraySegment<Byte> buffer = new ArraySegment<byte>(encoder.GetBytes( "{\"event\":\"loginBrowser\",\"data\":{\"login\":\"000000003077\",\"data\":\"1\"}}"));
await webSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
if (webSocket.State == WebSocketState.Open)
{
if (ShowMessage.created != true)
{
var dummy = new Control(); // to initialize SynchronizationContext
_sync = SynchronizationContext.Current;
new Thread(ThreadProc).Start();
}
await Receive(webSocket);
}
}
private static async Task Receive(ClientWebSocket webSocket)
{
while (webSocket.State == WebSocketState.Open)
{
ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[256]);
var result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
else
{
if (result.EndOfMessage)
{
message += encoder.GetString(buffer.ToArray());
SendMessage(message);
}
else
{
message += encoder.GetString(buffer.ToArray());
}
}
}
}
public static void ShowFormFromAnotherThread(string text)
{
_sync.Post(SendOrPostCallback, text);
}
private static void SendOrPostCallback(object state)
{
var form = new Notification();
form.Text = (string)state;
form.Show();
}
private static void ThreadProc()
{
while (true)
{
Thread.Sleep(2000); // wait imitation
ShowFormFromAnotherThread("HI");
}
}
/*Notification is my form and depending on where I put this part:
var dummy = new Control(); // to initialize SynchronizationContext
_sync = SynchronizationContext.Current;
new Thread(ThreadProc).Start();
//Main
运行(新的SocketService());
//SocketService类
公共SocketService()
{
alerta=null;
while(true)
{
尝试
{
//WriteLine(“Nome do Usúario:+Environment.UserName”);
《睡眠》(2000年);
连接(“ws://192.168.120.38:9091”).Wait();
}
捕获(例外情况除外)
{
控制台写入线(ex);
}
}
}
公共静态异步任务连接(字符串uri)
{
ClientWebSocket-webSocket=null;
尝试
{
webSocket=新客户端webSocket();
等待webSocket.ConnectAsync(新Uri(Uri),CancellationToken.None);
等待登录(webSocket);
}
捕获(例外情况除外)
{
掷骰子;
}
最后
{
如果(webSocket!=null)
Dispose();
锁(控制台锁)
{
Console.ForegroundColor=ConsoleColor.Red;
Console.WriteLine(“WebSocket关闭”);
Console.ResetColor();
}
}
}
专用静态异步任务登录(ClientWebSocket webSocket)
{
ArraySegment buffer=新的ArraySegment(encoder.GetBytes(“{\”事件\“:\”登录\“,\”数据\“:{\”登录\“:\”000000003077\”,\”数据\“:\”1\”}”);
等待webSocket.SendAsync(缓冲区,WebSocketMessageType.Text,true,CancellationToken.None);
if(webSocket.State==WebSocketState.Open)
{
如果(ShowMessage.created!=true)
{
var dummy=new Control();//初始化SynchronizationContext
_sync=SynchronizationContext.Current;
新线程(ThreadProc.Start();
}
等待接收(webSocket);
}
}
专用静态异步任务接收(ClientWebSocket webSocket)
{
while(webSocket.State==WebSocketState.Open)
{
ArraySegment缓冲区=新的ArraySegment(新字节[256]);
var结果=等待webSocket.ReceiveAsync(缓冲区,CancellationToken.None);
if(result.MessageType==WebSocketMessageType.Close)
{
等待webSocket.CloseAsync(WebSocketCloseStatus.NormalClose,string.Empty,CancellationToken.None);
}
其他的
{
if(result.EndOfMessage)
{
message+=encoder.GetString(buffer.ToArray());
发送消息(message);
}
其他的
{
message+=encoder.GetString(buffer.ToArray());
}
}
}
}
另一个线程的公共静态void showForm(字符串文本)
{
_sync.Post(SendOrPostCallback,text);
}
私有静态void SendOrPostCallback(对象状态)
{
var form=新通知();
Text=(字符串)状态;
form.Show();
}
私有静态void ThreadProc()
{
while(true)
{
Thread.Sleep(2000);//等待模仿
显示来自另一个线程(“HI”);
}
}
/*通知是我的表格,取决于我把这部分放在哪里:
var dummy=新控件();//初始化SynchronizationContext的步骤
_sync=SynchronizationContext.Current;
新线程(ThreadProc.Start();
或者我没有调用login,或者没有输入receive()方法,或者它接收信息的最佳情况
从另一个线程调用threadProc和showForm,但不输入SednOrPostCallBack*/尝试调用:
using System.Threading;
using System.Windows.Forms;
namespace ConsoleThreadSync
{
internal class Program
{
private static void Main(string[] args)
{
Application.Run(new App());
}
}
public class App : ApplicationContext
{
private readonly SynchronizationContext _sync;
public App()
{
var dummy = new Control(); // to initialize SynchronizationContext
_sync = SynchronizationContext.Current;
new Thread(ThreadProc).Start();
}
public void ShowFormFromAnotherThread(string text)
{
_sync.Post(SendOrPostCallback, text);
}
private void SendOrPostCallback(object state)
{
var form = new Form1();
form.Text = (string)state;
form.Show();
}
private void ThreadProc()
{
while (true)
{
Thread.Sleep(2000); // wait imitation
ShowFormFromAnotherThread("HI");
}
}
}
}
var dummy = new Control(); // to initialize SynchronizationContext
_sync = SynchronizationContext.Current;
从构造函数SocketService()而不是从
namespace ReiDoCSharp
{
class ShowMessage
{
private static RootObject alerta;
public static bool created;
private static int startPosition;
public static void setStartPosition(int start)
{
if (start < startPosition)
{
startPosition = start;
}
}
public RootObject getAlerta()
{
return ShowMessage.alerta;
}
public void setAlerta(RootObject root)
{
ShowMessage.alerta = root;
}
private static void DoWork()
{
while (true)
{
if (created != true)
{
created = true;
}
if (alerta != null)
{
string mensagem = "";
if ((alerta.data.Informacoes[1] != "") && (alerta.data.Informacoes[1] != null))
{
mensagem += alerta.data.Informacoes[1];
}
if ((alerta.data.Informacoes[0] != "") && (alerta.data.Informacoes[0] != null))
{
mensagem += alerta.data.Informacoes[0];
}
if (mensagem != "")
{
startPosition = 5;
string[] messages = mensagem.Split(new[] { "<br><br>" }, StringSplitOptions.None);
foreach (string message in messages)
{
Notification popup = new Notification();
popup.label1.Text = message;
popup.TopMost = true;
popup.Show();
Application.DoEvents();
/*Solution with the ShowDialog would be:
Task.Run(() => showNotification(message));
*/
}
}
}
Thread.Sleep(5000);
}
}
//Then I won't need to use Application.DoEvents, but would have to create more threads
private static Task showNotification(string message)
{
Notification popup = new Notification();
popup.label1.Text = message;
popup.TopMost = true;
popup.ShowDialog();
}
public static Task createPopupsAsync()
{
Task.Run(() => DoWork());
}
}
}
namespace ReiDoCSharp
{
class SocketService
{
private static object consoleLock = new object();
private const bool verbose = true;
private static readonly TimeSpan delay = TimeSpan.FromMilliseconds(3000);
private static UTF8Encoding encoder = new UTF8Encoding();
private static string message;
private static RootObject alerta;
public SocketService()
{
Begin();
}
public static void Begin()
{
alerta = null;
while (true)
{
try
{
Thread.Sleep(2000);
Connect("ws://192.168.120.38:9091").Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
public static async Task Connect(string uri)
{
ClientWebSocket webSocket = null;
try
{
webSocket = new ClientWebSocket();
await webSocket.ConnectAsync(new Uri(uri), CancellationToken.None);
await Login(webSocket);
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (webSocket != null)
webSocket.Dispose();
lock (consoleLock)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("WebSocket closed.");
Console.ResetColor();
}
}
}
private static async Task Login(ClientWebSocket webSocket)
{
ArraySegment<Byte> buffer = new ArraySegment<byte>(encoder.GetBytes("{\"event\":\"loginBrowser\",\"data\":{\"OPERADOR\":\"000000003077\",\"NRORG\":\"1\"}}"));
await webSocket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
if (webSocket.State == WebSocketState.Open)
{
Task.Factory.StartNew(() => ShowMessage.createPopupsAsync());
await Receive(webSocket);
}
}
private static async Task Receive(ClientWebSocket webSocket)
{
while (webSocket.State == WebSocketState.Open)
{
ArraySegment<Byte> buffer = new ArraySegment<byte>(new Byte[256]);
var result = await webSocket.ReceiveAsync(buffer, CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
}
else
{
if (result.EndOfMessage)
{
message += encoder.GetString(buffer.ToArray());
SendMessage(message);
}
else
{
message += encoder.GetString(buffer.ToArray());
}
}
}
}
private static void LogStatus(bool receiving, byte[] buffer, int length, string assunto)
{
lock (consoleLock)
{
Console.ForegroundColor = receiving ? ConsoleColor.Green : ConsoleColor.Yellow;
if (verbose)
{
Console.WriteLine(encoder.GetString(buffer) + " " + assunto);
}
Console.ResetColor();
}
}
private static void SendMessage(string message)
{
message = message.Replace("event", "evento");
message = message.Replace("\0", "");
JavaScriptSerializer js = new JavaScriptSerializer();
RootObject mess = js.Deserialize<RootObject>(message);
if (mess.data.Informacoes[1] != "")
{
mess.data.Informacoes[1] += "<br>";
}
if (alerta == null)
{
alerta = mess;
}
else
{
if ((mess.data.Quantidade[0] != 0) && (mess.data.Quantidade == null))
{
if ((mess.data.Quantidade[0] == -1) && (mess.data.Informacoes[0] == ""))
{
alerta = null;
}
else
{
alerta = mess;
}
}
else if (mess.data.Quantidade[0] == 0)
{
alerta = null;
}
if ((mess.data.Quantidade[1] != 0) && (mess.data.Informacoes[1] != ""))
{
alerta = mess;
}
}
new ShowMessage().setAlerta(alerta);
message = "";
}
}
}