What is the easiest way to perform background tasks in Windows.Forms?

Background tasks are things that are related to network I / O, disk I / O, or other long-term tasks that may or may not be performed over the network. It is often mixed with code that updates the GUI that needs to be run on another thread, the GUI thread.

The simple meaning is that when you open the Form.cs file, the source code is as easy or easier to read as before. In practice, the source code stream should still be read sequentially with respect to the order in which the code is executed, regardless of which stream it runs. All supporting tissue should be reused and hidden somewhere, and not included in each form.

Google for Google search: it turned out that the solution officially sanctioned by Microsoft is System.ComponentModel.BackgroundWorker, which falls (very!) To the second point.

(There is also an officially approved Silverlight / XAML / 3.5 model in System.Windows.Threading.Dispatcher.)

+3
source share
8 answers

This is the simplest idea I came up with. It may be completely incompatible, I encoded incredibly close to null Windows.Forms applications.

, : Background() Foreground(). , -. Background() . Foreground() "" GUI .BeginInvoke() .

, .

public class Form1 : Form {
    protected ProgressBar progressBar1;
    protected Button button1;

    protected BackgroundHelper helper = new BackgroundHelper();

    public void button1_Click(...) {
        // Execute code in the background.
        helper.Background(() => {
            for (int i = 0; i <= 100; i++) {
                // Continually report progress to user.
                helper.Foreground<int>(i, j => {
                    progressBar1.Value = j;
                });
                // Simulate doing I/O or whatever.
                Thread.Sleep(25);
            }
        });
    }
}

, , .

, ,

  • , .
  • Background() Foreground() .
  • Background() .
  • Foreground() , BeginInvoke GUI, .

EDIT: :
http://code.google.com/p/backgrounder/

+1

BackgroundWorker, , .

+3

BackgroundWorker. . , .

, .

+2

, , BackgroundWorker ?

2-3 .

+1

/, , File-scanner ( 100- ). , , .

, . , .

, " - , ", , . .

...

Public Class FileScanner
    Public Event Scan_Complete(sender As Object)
    Public Event Scan_Update(sender As Object, filename As String)
    Public Event Scan_Error(sender As Object, ex As Exception)
    Private Delegate Sub del_ScanComplete()

    Sub New(syncObject As Control, path String)
        Me.SynchronizeObject = syncObject
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf ScanFilesAsync), path)
    End Sub

    Private Sub ScanFilesAsync(ByVal state As Object)

        ' scan files here

        ' call the method to raise the Complete event
        ScanComplete()

    End Sub

    Private Sub ScanComplete()

        If SynchronizeObject.InvokeRequired Then
            ' we cant raise event on a different thread than our caller
            ' so lets invoke our method on the same caller thread
            Dim d As New del_ScanComplete(AddressOf ScanComplete)
            SynchronizeObject.Invoke(d)
        Else
            ' no synchronize needed, tell the caller we are done
            RaiseEvent Complete(Me)
        End If

    End Sub

End Class
0

Windows Forms , , AsyncOperationManager AsyncOperation. , AsyncOperation . UI InvokeRequired.

public class BackgroundTask{

  private AsyncOperation _asyncOperation;
  public EventHandler Done;

  public BackgroundTask(){
    _asyncOperation = AsyncOperationManager.CreateOperation();
  }

  public void DoAsync(object userState) {
    System.Threading.ThreadPool.QueueUserWorkItem( ExecuteDo, userState);
  }

  private void ExecuteDo(object state) {
    // Do your work here
    // Raise event after finish
    _asyncOperation.PostOperationCompleted( Finished, EventArgs.Empty );
  }

  private void LookUpFinished( object eventargs ) {
    OnDone( ( EventArgs) eventargs );
  }

  private void OnDone( LookUpEventArgs e ) {
    EventHandler localEvent = Done;
    if ( localEvent!= null ) {
      localEvent(this,e);
    } 
  }
}

, :

public class MyForm : Form {

  public MyForm() {
    InitializeComponent();
  }

  protected override OnShown(EventArgs e) {
    BackgroundTask task = new BackgroundTask();
    task.Done += SignalTaskDone;
  }

  private void SignalTaskDone(object sender, EventArgs e){
    MessageBox.Show(this, "Task finished");
  }
}
0

As convincingly proven here , Microsoft has discovered flaws in BackgroundWorker, and you can get much better, clearer code using Task.Run with the async keyword.

0
source

Source: https://habr.com/ru/post/1719372/


All Articles