none
BackgroundWorker / übergabe von Objekt RRS feed

  • Frage

  • Hallo,

    ReportProgress kann ich über einen Background Worker ausgeben, das funktioniert. Gibt es auch eine Möglichkeit z.B. einen String an die GUI zu übermitteln?

    vielen Dank

     


    Mittwoch, 21. September 2011 21:10

Antworten

  • Hallo,

    Es gibt eine Überladung der Methode ReportProgress, die zwei Parameter besitzt: Int32 und Object. Den letzten Parameter hat man bewußt als Object belassen, damit man einen beliebigen Zustand (userState) an den UI-Thread übergeben kann. Du kannst im userState einen String aber auch eine Instanz einer beliebigen anderen Klasse übergeben. Beim Verarbeiten auf dem UI-Thread im ProgressChanged-Ereignishandler mußt Du nur korrekt casten:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
       backgroundWorker.ReportProgress(100, "Complete!");
    }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       toolStripStatusLabel.Text = e.UserState as String;
    }
    

    Im obigen Beispiel, das aus der MSDN-Dokumentation stammt, wird der String "Complete!" an die UI übermittelt. Schau dir das Beispiel in Ruhe an. Dort findest Du auch, wie man auf ein UI-Steuerelement über einen Delegate bzw. Control.Invoke() aus einem Fremdthread sicher zugreift.

    BackgroundWorker.ReportProgress-Methode (Int32, Object):
    http://msdn.microsoft.com/de-de/library/a3zbdb1t.aspx

    Den vollständigen Code findest Du hier:
    http://msdn.microsoft.com/de-de/library/system.windows.forms.toolstripprogressbar.aspx


    Gruß
    Marcel

    Donnerstag, 22. September 2011 05:50
    Moderator

Alle Antworten

  • Hallo,

    Es gibt eine Überladung der Methode ReportProgress, die zwei Parameter besitzt: Int32 und Object. Den letzten Parameter hat man bewußt als Object belassen, damit man einen beliebigen Zustand (userState) an den UI-Thread übergeben kann. Du kannst im userState einen String aber auch eine Instanz einer beliebigen anderen Klasse übergeben. Beim Verarbeiten auf dem UI-Thread im ProgressChanged-Ereignishandler mußt Du nur korrekt casten:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
       backgroundWorker.ReportProgress(100, "Complete!");
    }
    
    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
       toolStripStatusLabel.Text = e.UserState as String;
    }
    

    Im obigen Beispiel, das aus der MSDN-Dokumentation stammt, wird der String "Complete!" an die UI übermittelt. Schau dir das Beispiel in Ruhe an. Dort findest Du auch, wie man auf ein UI-Steuerelement über einen Delegate bzw. Control.Invoke() aus einem Fremdthread sicher zugreift.

    BackgroundWorker.ReportProgress-Methode (Int32, Object):
    http://msdn.microsoft.com/de-de/library/a3zbdb1t.aspx

    Den vollständigen Code findest Du hier:
    http://msdn.microsoft.com/de-de/library/system.windows.forms.toolstripprogressbar.aspx


    Gruß
    Marcel

    Donnerstag, 22. September 2011 05:50
    Moderator
  • Hallo Schlegel,

    Hat Dir die Antwort geholfen?

    Grüße,
    Robert

    Montag, 26. September 2011 14:04
    Moderator
  • Hallo Schlegel,

    Ich gehe davon aus, dass die Antworten Dir weitergeholfen haben.
    Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.

    Grüße,
    Robert

    Dienstag, 27. September 2011 12:41
    Moderator
  • Hallo,
    ich wage es ( ;-) ) meine erste Antwort zu schreiben.
    Als ich bei einem Projekt (sehr) viele Probleme mit dem BackgroundWorker hatte, habe ich mir sehr genau die Antworten von u. a. Marcel und Frank angeschaut. Meine Lösung sieht so aus:

    void backgroundWorker_DoWork_Task( object sender, DoWorkEventArgs e )
    
    {
    
        const int max = 127;
    
    
    
       BackgroundWorker bw = (BackgroundWorker) sender;
    
    
    
       bw.ReportProgress( 0, new ProgressInfo() { Maximum = max, Value = 0, Info = "Preparing task 2...", Style = ProgressBarStyle.Blocks } );
    
    
    
    Thread.Sleep( 2500 );
    
      for( int i = 0; i < max; i++ )
    
    	{
    
    	if( bw.CancellationPending )
    
    	{
    
    	    e.Cancel = true;
    
      	    break;
    
    				
    
    }
    
    
    
     bw.ReportProgress( 0, new ProgressInfo() { Maximum = max, Value = i, Info = "Task 2 is running...", Style = ProgressBarStyle.Marquee } );
    
    Thread.Sleep( 55 );
    
       }
    
    
    
    }
    
    
    die Klasse ProgressInfo sieht so aus:

    public class ProgressInfo
    
    	{
    
    		public static string InfoNofMText = "von";
    
    
    
    		#region Property: Minimum
    
    
    
    		private int _Minimum;
    
    
    
    		public int Minimum
    
    		{
    
    			get { return _Minimum; }
    
    			set { _Minimum = value; }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: Maximum
    
    
    
    		private int _Maximum;
    
    
    
    		public int Maximum
    
    		{
    
    			get { return _Maximum; }
    
    			set { _Maximum = value; }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: Value
    
    
    
    		private int _Value;
    
    
    
    		public int Value
    
    		{
    
    			get
    
    			{
    
    				if( _Value < _Minimum ) return _Minimum;
    
    				if( _Value > _Maximum ) return _Maximum;
    
    				return _Value;
    
    			}
    
    			set { _Value = value; }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: Style
    
    
    
    		private ProgressBarStyle _Style = ProgressBarStyle.Continuous;
    
    
    
    		public ProgressBarStyle Style
    
    		{
    
    			get { return _Style; }
    
    			set { _Style = value; }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: Info
    
    
    
    		private string _Info;
    
    
    
    		public string Info
    
    		{
    
    			get { return _Info; }
    
    			set { _Info = value; }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: ProgressPercentage
    
    
    
    		public float ProgressPercentage
    
    		{
    
    			get
    
    			{
    
    				float result = 1;
    
    
    
    				if( _Maximum > 0 )
    
    					result = ( _Value * 100 ) / ((float)_Maximum);
    
    
    
    				return result;
    
    			}
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: ProgressPercentageInt
    
    
    
    		public int ProgressPercentageInt
    
    		{
    
    			get { return Convert.ToInt32( this.ProgressPercentage ); }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: ProgressPercentageInfo
    
    
    
    		public string ProgressPercentageInfo
    
    		{
    
    			get { return this.ProgressPercentage.ToString( "F2" ) + " %"; }
    
    		}
    
    
    
    		#endregion
    
    
    
    		#region Property: InfoNofM
    
    
    
    		public string InfoNofM
    
    		{
    
    			get { return String.Format( "{0} {1} {2}", _Value, ProgressInfo.InfoNofMText, _Maximum - _Minimum ); }
    
    		}
    
    
    
    		#endregion
    
    	}
    
    

    ich hoffe, es hilft Dir weiter.
    P.

    hmm, es fehlt noch was (das Casting, wovon Marcel gesprochen hat..).
    _BackgroundWorker.ProgressChanged += new ProgressChangedEventHandler( backgroundWorker_ProgressChanged );
    
    
    void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
            {
                ProgressInfo pi = (ProgressInfo)e.UserState;
                SetProgressInfoGUI(pi);
            }
    
    void SetProgressInfoGUI( ProgressInfo progressInfo )
    {
    infoProgressBar.Minimum = progressInfo.Minimum;
    infoProgressBar.Maximum = progressInfo.Maximum;
    infoProgressBar.Style = progressInfo.Style;
    infoProgressBar.Value = progressInfo.Value;
    progressInfoLabel.Text = progressInfo.Info;
    progressNofMLabel.Text = progressInfo.InfoNofM;
    progressPercentageLabel.Text = progressInfo.ProgressPercentageInfo;
    }
    
    
    


    ...jetzt dürfte es komplett sein...
    P.

    • Bearbeitet Purclot Dienstag, 27. September 2011 15:07
    Dienstag, 27. September 2011 14:24