Answer the question
In order to leave comments, you need to log in
C# How to update form control from another thread?
Forgive the slowpack, but how to update the control on the form from another thread?
I tried to attach a delegate here, but somehow unsuccessfully.
The transfer must occur from the SendStr function.
using ...;
namespace Ping_test
{
public delegate void Del(string str);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Del Call = new Del(UpdateRes);
}
private void button1_Click(object sender, EventArgs e)
{
new PingExample().Start( "192.168.1.1",10);
}
}
public class PingExample
{
private int Count = 0;
private int Cycle = 0;
private string ip = string.Empty;
public PingExample()
{
TTimer = new System.Threading.Timer(new TimerCallback(OnTimer), TimerRun, System.Threading.Timeout.Infinite, 1000);
}
public void Start(string ip_str, int Raz)
{
Count = 1;
Cycle = Raz;
ip = ip_str;
TTimer.Change(0, 1000);
}
private void OnTimer(object state)
{
if (Count <= Cycle)
{
Go();
}
}
public void Go()
{
AutoResetEvent waiter = new AutoResetEvent(false);
Ping pingSender = new Ping();
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
string data = "ID:<" + String.Format(@"{0,5:d}", Count.ToString()) + ">**********************";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 1000;
PingOptions options = new PingOptions(64, true);
pingSender.SendAsync(ip, timeout, buffer, options, waiter);
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
// If the operation was canceled, display a message to the user.
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
((AutoResetEvent)e.UserState).Set();
}
if (e.Error != null)
{
Console.WriteLine("#" + Count.ToString() + " " + ip + " Ping failed: ");
Console.WriteLine(e.Error.ToString());
((AutoResetEvent)e.UserState).Set();
}
PingReply reply = e.Reply;
DisplayReply(reply);
((AutoResetEvent)e.UserState).Set();
Count++;
}
public void DisplayReply(PingReply reply)
{
if (reply == null)
return;
string Num = "#" + String.Format(@"{0,5:d}", Count.ToString());
if (reply.Status == IPStatus.Success)
{
string res = Num + " " + reply.Address.ToString() + " RTT " + reply.RoundtripTime.ToString() + " TTL " + reply.Options.Ttl.ToString() + " BUFFER " + reply.Buffer.Length.ToString();
res += " \"" + System.Text.ASCIIEncoding.ASCII.GetString(reply.Buffer) + "\"";
SendStr(res);
}
else
{
string res = Num + " " + ip + " ERROR: " + reply.Status.ToString();
SendStr(res);
}
}
void SendStr(string str);
{
}
}
Answer the question
In order to leave comments, you need to log in
can be even easier
BeginInvoke(new MethodInvoker(delegate
{
//здесь твой код в основном потоке
}));
BackgroundWorker:
msdn.microsoft.com/en-us/library/system.componentm...
it has an OnProgressChanged event that will be called on the form's thread. to generate an event in doWork, you need to call the ReportProgress method msdn.microsoft.com/ru-ru/library/a3zbdb1t.aspx it
is not necessary to define methods, you can use lambdas:
backgroundWorker.DoWork += (sender, e) => { ... };
backgroundWorker.DoWork += delegate { ... };
Remember Dispatcher.CurrentDispatcher when creating the form, and update the UI from another thread using Dispatcher.BeginInvoke.
Well, for example like this:
// some background thread code
Form1.Dispatcher.Invoke(DispatcherPriority.ContextIdle, new Action(delegate()
{
label1.Content="invoked from background thread";
}));
How to call BackgroundWorker.OnProgressChanged from
I understand that in order to take advantage of the charms of the BackgroundWorker - you need to shove a procedure into it that will run in the background and it will already be able to call OnProgressChanged.
I have a slightly different situation.
If the thread is running somewhere in the business layer and does not know about the form, then a synchronization context can be used. Like this:
When creating the form:
SynchronizationContext uiContext = SynchronizationContext.Current;
Thread thread = new Thread(Run);
// Запустим поток и установим ему контекст синхронизации,
// таким образом этот поток сможет обновлять UI
thread.Start(uiContext);
private void Run(object state)
{
// вытащим контекст синхронизации из state'а
SynchronizationContext uiContext = state as SynchronizationContext;
// говорим что в UI потоке нужно выполнить метод UpdateUI
// и передать ему в качестве аргумента строку
uiContext.Post(UpdateUI, "Hello world!");
}
/// <summary>
/// Этот метод исполняется в основном UI потоке
/// </summary>
private void UpdateUI(object state)
{
sampleListBox.Items.Add((string)state);
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question