你好,
我正在嘗試撰寫一個偵聽埠的 UDP 客戶端,然后在文本框中顯示傳入的資料。
我寫了一堂課;UDP_Receive() 啟動一個后臺作業程式,該作業程式偵聽指定埠并接收資料。代碼基于這個問題;C# .Net 在分離執行緒和應用程式退出中接收 UDp 資料包
我想我已經通過遵循這個問題中接受的答案解決了阻塞 .receive() 的問題;如果超時,如何安全地終止 UdpClient.receive()?
我的問題是如何將我在后臺作業執行緒(我在我的類中創建)中收到的資料回傳到主執行緒,以便我可以在文本框中顯示它?
我曾想過使用 Invoke,但我的課堂上沒有對文本框的任何參考。
textBox_UdpPositionInData.Invoke(new EventHandler(delegate
{
textBox_UdpPositionInData.Text = receivedData;
}));
我發現了一個關于 tcp-server 的非常相似的問題,但我看不到如何在此處應用該解決方案Send data from a background thread to the main thread
任何想法或建議當然都非常感謝!
非常感謝!
internal class UDP_Receive
{
private int _portToListen = 2003;
private volatile bool listening;
BackgroundWorker _backgroundWorker;
//Constructor
public UDP_Receive()
{
Debug.WriteLine("Constructor: UDP_Receive");
this.listening = false;
}
public void StartListener()
{
if ( (_backgroundWorker==null) || (!_backgroundWorker.IsBusy))
{
_backgroundWorker = new BackgroundWorker();
_backgroundWorker.DoWork = listenForUDPPackages_DoWork;
_backgroundWorker.RunWorkerCompleted =listenForUDPPackages_RunWorkerCompleted;
_backgroundWorker.WorkerSupportsCancellation = true;
_backgroundWorker.RunWorkerAsync();
Debug.WriteLine("Creates a new thread: " _backgroundWorker.ToString() );
// We are listening
this.listening = true;
}
}
public void StopListener()
{
// The user cancelled the UDP Port listening
this.listening = false;
// Cancel the backgroundworker
_backgroundWorker.CancelAsync();
// Debug
Debug.WriteLine("Stops current thread: " _backgroundWorker.ToString());
}
public bool IsListening
{
get { return this.listening; }
}
public int PortToListen
{
get { return this._portToListen; }
set { this._portToListen = value; }
}
private void listenForUDPPackages_DoWork(object sender, DoWorkEventArgs ev)
{
UdpClient? listener = null;
try
{
listener = new UdpClient(_portToListen);
}
catch (SocketException)
{
//do nothing
}
if (listener != null)
{
IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, _portToListen);
try
{
while (this.listening)
{
Debug.WriteLine("Waiting for UDP broadcast to port " _portToListen);
byte[] receivedBytes = new byte[1024];
string receivedData;
bool timeTracker = TrackFunction(TimeSpan.FromSeconds(2), () =>
{
receivedBytes = listener.Receive(ref groupEP);
});
Debug.WriteLine("Timetracker result: " timeTracker.ToString());
if (receivedBytes == null || receivedBytes.Length == 0)
{
// We did not recieve any data
Debug.WriteLine("No data received befor Time out ");
}
else
{
// We managed to receive some data!
// No we want to process the data and then send the result to the Thread that initiated the class.
receivedData = Encoding.Default.GetString(receivedBytes);
Debug.WriteLine("Data received: " receivedData);
}
}
catch (Exception e)
{
Debug.WriteLine("Exception: " e.ToString());
}
finally
{
listener.Close();
Debug.WriteLine("Finally: Done listening for UDP broadcast");
}
}
else
{
Debug.WriteLine("Error: UdpClient(_portToListen) returned null");
}
}
private void listenForUDPPackages_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e == null || e.Result == null)
{
Debug.WriteLine("listenForUDPPackages_RunWorkerCompleted e = null");
}
else
{
if (e.Cancelled)
{
Debug.WriteLine("Operation was canceled");
}
else if (e.Error != null)
{
Debug.WriteLine("Error: " e.Error.Message);
}
else
{
Debug.WriteLine("Result: " e.Result.ToString());
}
}
}
private static bool TrackFunction(TimeSpan timeSpan, Action codeBlock)
{
try
{
Task task = Task.Factory.StartNew(() => codeBlock());
task.Wait(timeSpan);
return task.IsCompleted;
}
catch (AggregateException ae)
{
throw ae.InnerExceptions[0];
}
}
}
uj5u.com熱心網友回復:
您可以撰寫這種代碼來將 UI 與UDP_Receive類分開:
internal class UDP_Receive
{
private Action<string> _invoke;
public UDP_Receive(Action<string> invoke)
{
_invoke = invoke;
}
public void Foo()
{
_invoke("Hello");
}
}
當你宣告類時,你會這樣做:
var ur = new UDP_Receive(t => textBox.Invoke(() => textBox.Text = t));
現在只需呼叫ur.Foo()(在我的示例中)來更新 UI。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/430572.html
