0

I know this may have been asked previously, but I cannot find a fix for my solution. Any insight would be appreciated, I will list the code below with quotations. I've over-read that Dispatcher.BeginInvoke only works within WPF. How would I manage to get this work in Winforms? I am working on an application that transfers a trace-route output to a list-box on a button click. I receive an error saying:

// An object reference is required for the non-static field, method, or property 'Dispatcher.BeginInvoke(Delegate, params object[])' //

    private void WriteListBox(string text)
    {
        NewMethod(text);
    }

    private void NewMethod(string text)
    {
        Dispatcher.BeginInvoke(new Action(() =>
        {
            lbRoute.Items.Add(text);
        }));
    }

    private void btnTrace_Click(object sender, EventArgs e)
    {
        string hostname = txtTracehost.Text;
        int timeout = 1000;
        int max_ttl = 30;
        int current_ttl = 0;
        const int bufferSize = 32;
        Stopwatch s1 = new Stopwatch();
        Stopwatch s2 = new Stopwatch();
        byte[] buffer = new byte[bufferSize];
        new Random().NextBytes(buffer);
        Ping pinger = new Ping();
        Task.Factory.StartNew(() =>
        {
            WriteListBox($"Started ICMP Trace route on {hostname}");
            for (int ttl = 1; ttl <= max_ttl; ttl++)
            {
                current_ttl++;
                s1.Start();
                s2.Start();
                PingOptions options = new PingOptions(ttl, true);
                PingReply reply = null;
                try
                {
                    reply = pinger.Send(hostname, timeout, buffer, options);
                }
                catch
                {
                    WriteListBox("Error");
                    break;
                }
                if (reply != null)
                {
                    if (reply.Status == IPStatus.TtlExpired)
                    {
                        WriteListBox($"[{current_ttl}] - Route: {reply.Address} - Time: { s1.ElapsedMilliseconds} ms - Total Time: {s2.ElapsedMilliseconds} ms");
                        continue;
                    }
                    if (reply.Status == IPStatus.TimedOut)
                    {
                        WriteListBox($"Timeout on {hostname}. Continuing.");
                        continue;
                    }
                    if (reply.Status == IPStatus.Success)
                    {
                        WriteListBox($"Successful Trace Route to {hostname} in {s1.ElapsedMilliseconds} ms - Total Time: {s2.ElapsedMilliseconds} ms");
                        s1.Stop();
                        s2.Stop();
                        
                    }
                }
            }
        });
    }
  • [How to avoid cross-thread operation not valid exception in Winform](https://stackoverflow.com/a/62449011/7444103). As described, you can use `System.Windows.Threading.Dispatcher` in WinForms, but read the notes. Anyway, the other 3 methods get the job done. – Jimi Jun 22 '20 at 23:21
  • One thing to note... If you make all your slow operations Async and you partition your problem correctly (so that background work happens asynchronously and foreground work in, well, the foreground) you can do a lot in WinForms with just `async` and `await` and not worrying (too much) about threads at all. – Flydog57 Jun 23 '20 at 00:54

0 Answers0