Hallo Community,
ich habe eine Frage zu Events by asynchronen Methoden.
Bei Stackoverflow habe ich ein Beispiel gefunden (nachfolgender Code) und frage mich ob es auch anders funktioniert.
Mein aktueller Code:
Traceroute
TracerouteInfo
TracerouteArgs
ViewModel
Nun zu meiner Frage:
Momentan übergebe ich ja für alles eine Action (z.B. wenn ein Hop gefunden wurde), damit ich dem Benutzer live zeige das was passiert und nicht erst nach x-Sekunden das Gesamtergebnis liefere:
Gibt es auch die Möglichkeit das ganze so zu schreiben, damit ich ein Event abonnieren kann? Also mit Eventhandler und Delegate? Das ganze soll aber asynchron laufen damit die UI nicht blockiert.
In etwa so...
ich habe eine Frage zu Events by asynchronen Methoden.
Bei Stackoverflow habe ich ein Beispiel gefunden (nachfolgender Code) und frage mich ob es auch anders funktioniert.
Mein aktueller Code:
C#-Quellcode
- public class Traceroute
- {
- public void Trace(TracerouteInfo info, Action<TracerouteArgs> TouteReceived, Action TraceCompleted, Action UserHasCanceled, CancellationToken cancellationToken)
- {
- Task.Run(() =>
- {
- byte[] buffer = new byte[info.Buffer];
- Stopwatch stopwatch = new Stopwatch();
- using (Ping ping = new Ping())
- {
- try
- {
- for (int hop = 1; hop < info.MaximumHops; hop++)
- {
- // If user has clicked cancel
- cancellationToken.ThrowIfCancellationRequested();
- stopwatch.Start();
- PingReply pingReply = ping.Send(info.IPAddress, info.Timeout, buffer, new PingOptions() { Ttl = hop, DontFragment = info.DontFragement });
- stopwatch.Stop();
- string hostname = string.Empty;
- try
- {
- if (pingReply.Address != null)
- hostname = Dns.GetHostEntry(pingReply.Address).HostName;
- }
- catch (SocketException) { } // Couldn't resolve hostname
- TouteReceived(new TracerouteArgs(hop, stopwatch.ElapsedMilliseconds, pingReply.Address, hostname, pingReply.Status));
- if (pingReply.Address != null)
- {
- if (pingReply.Address.ToString() == info.IPAddress.ToString())
- {
- TraceCompleted();
- return;
- }
- stopwatch.Reset();
- }
- }
- }
- catch (OperationCanceledException)
- {
- UserHasCanceled();
- }
- }
- }, cancellationToken);
- }
- }
C#-Quellcode
- public class TracerouteInfo
- {
- public IPAddress IPAddress;
- public int Timeout;
- public int Buffer;
- public int MaximumHops;
- public bool DontFragement;
- public TracerouteInfo()
- {
- }
- public TracerouteInfo(IPAddress ipAddress, int timeout, int buffer, int maximumHops, bool dontFragement)
- {
- IPAddress = ipAddress;
- Timeout = timeout;
- Buffer = buffer;
- MaximumHops = maximumHops;
- DontFragement = dontFragement;
- }
- }
C#-Quellcode
- public class TracerouteArgs : EventArgs
- {
- public int Hop { get; set; }
- public double Time { get; set; }
- public IPAddress IPAddress { get; set; }
- public string Hostname { get; set; }
- public IPStatus Status { get; set; }
- public TracerouteArgs()
- {
- }
- public TracerouteArgs(int hop, double time, IPAddress ipAddress, string hostname, IPStatus status)
- {
- Hop = hop;
- Time = time;
- IPAddress = ipAddress;
- Hostname = hostname;
- Status = status;
- }
- }
C#-Quellcode
- public ICommand TraceCommand
- {
- get { return new RelayCommand(p => TraceAction()); }
- }
- private void TraceAction()
- {
- if (IsTraceRunning)
- StopTrace();
- else
- StartTrace();
- }
- CancellationTokenSource sourceToken;
- private async void StartTrace()
- {
- IsTraceRunning = true;
- TraceResult.Clear();
- // Try to parse the string into an IP-Address
- IPAddress ipAddress;
- IPAddress.TryParse(HostnameOrIPAddress, out ipAddress);
- try
- {
- // Try to resolve the hostname
- if (ipAddress == null)
- {
- IPHostEntry ipHostEntrys = await Dns.GetHostEntryAsync(HostnameOrIPAddress);
- foreach (IPAddress ip in ipHostEntrys.AddressList)
- {
- if (ip.AddressFamily == AddressFamily.InterNetwork && ResolveHostnamePreferIPv4)
- {
- ipAddress = ip;
- continue;
- }
- else if (ip.AddressFamily == AddressFamily.InterNetworkV6 && !ResolveHostnamePreferIPv4)
- {
- ipAddress = ip;
- continue;
- }
- }
- // Fallback --> If we could not resolve our prefered ip protocol
- if (ipAddress == null)
- {
- foreach (IPAddress ip in ipHostEntrys.AddressList)
- {
- ipAddress = ip;
- continue;
- }
- }
- }
- // Add the hostname or ip address to the history
- HostnameOrIPAddressHistory = new List<string>(HistoryListHelper.Modify(HostnameOrIPAddressHistory, HostnameOrIPAddress, 5));
- // Traceroute
- TracerouteInfo info = new TracerouteInfo
- {
- IPAddress = ipAddress,
- Timeout = Timeout,
- Buffer = Buffer,
- MaximumHops = MaximumHops,
- DontFragement = true
- };
- sourceToken = new CancellationTokenSource();
- Traceroute traceroute = new Traceroute();
- traceroute.Trace(info, Traceroute_HopReceived, Traceroute_TraceComplete, Traceroute_UserHasCanceled, sourceToken.Token);
- }
- catch (SocketException) // This will catch DNS resolve errors
- {
- MetroDialogSettings dialogSettings = new MetroDialogSettings();
- dialogSettings.CustomResourceDictionary = new ResourceDictionary
- {
- Source = new Uri("NETworkManager;component/Resources/Styles/MetroDialogStyles.xaml", UriKind.RelativeOrAbsolute)
- };
- await dialogCoordinator.ShowMessageAsync(this, Application.Current.Resources["String_Header_DnsError"] as string, Application.Current.Resources["String_CouldNotResolveHostname"] as string, MessageDialogStyle.Affirmative, dialogSettings);
- }
- catch (Exception ex) // This will catch any exception
- {
- MetroDialogSettings dialogSettings = new MetroDialogSettings();
- dialogSettings.CustomResourceDictionary = new ResourceDictionary
- {
- Source = new Uri("NETworkManager;component/Resources/Styles/MetroDialogStyles.xaml", UriKind.RelativeOrAbsolute)
- };
- await dialogCoordinator.ShowMessageAsync(this, Application.Current.Resources["String_Error"] as string, ex.Message, MessageDialogStyle.Affirmative, dialogSettings);
- }
- }
- private void Traceroute_UserHasCanceled()
- {
- IsTraceRunning = false;
- MessageBox.Show("canceld by user");
- }
- private void Traceroute_HopReceived(TracerouteArgs args)
- {
- // Add result
- Application.Current.Dispatcher.BeginInvoke(new Action(delegate ()
- {
- TraceResult.Add(args);
- }));
- }
- private void Traceroute_TraceComplete()
- {
- IsTraceRunning = false;
- }
- private void StopTrace()
- {
- sourceToken.Cancel();
- }
Nun zu meiner Frage:
Momentan übergebe ich ja für alles eine Action (z.B. wenn ein Hop gefunden wurde), damit ich dem Benutzer live zeige das was passiert und nicht erst nach x-Sekunden das Gesamtergebnis liefere:
traceroute.Trace(info, Traceroute_HopReceived, Traceroute_TraceComplete, Traceroute_UserHasCanceled, sourceToken.Token);
Gibt es auch die Möglichkeit das ganze so zu schreiben, damit ich ein Event abonnieren kann? Also mit Eventhandler und Delegate? Das ganze soll aber asynchron laufen damit die UI nicht blockiert.
In etwa so...
NETworkManager - A powerful tool for managing networks and troubleshoot network problems!