2016-08-05 28 views
0

Ich habe eine sehr einfache Form mit einem Fortschrittsbalken darauf und eine Schaltfläche zum Löschen. Wenn der Benutzer auf "Löschen" klickt, wird eine gespeicherte Prozedur für ungefähr fünf Minuten ausgeführt.Ist es möglich, eine einfache C# Marquee Progress Bar ohne Hintergrundarbeiter zu machen?

Ich möchte eine einfache Laufschrift Fortschrittsbalken ausführen, aber es erscheint nie. Ich habe alle anderen Fragen dazu gelesen, aber alle benötigten einen Hintergrundarbeiter.

Ist es möglich, einen Marquee-Fortschrittsbalken ohne Hintergrundarbeiter zu erstellen?

public partial class ProgressBarSample 
{ 
    public ProgressBarSample 

     { 
      progressBar1.Style = ProgressBarStyle.Marquee; 
      progressBar1.Visible = false; 
     } 


    private void btnDelete_Click(object sender, EventArgs e) 
     { 
      progressBar1.Visible = true; 
      // run stored procedure that takes around 5 minutes 
      Task.Delay(10000); 
      progressBar1.Visible = false; 
     } 
} 

Antwort

1

Ihr Code

progressBar1.Visible = true; 
// run stored procedure that takes around 5 minutes 
Task.Delay(10000); 
progressBar1.Visible = false; 

verhindert Windows-Nachrichten aus Ihrer Anwendung verarbeitet werden, bis die Verzögerung abgeschlossen ist, weil Sie den Thread für die Verarbeitung dieser Nachrichten blockieren. Windows verlässt sich darauf, dass diese Nachrichten zeitnah verarbeitet werden.

Das Ergebnis ist, dass Ihre Benutzeroberfläche für den Benutzer nicht mehr reagiert.

Es gibt eine Reihe von Mechanismen, mit denen Sie Ihre Verarbeitung in einem zweiten Thread durchführen können. BackgroundWorker ist eine, die zu der Zeit verwendet wurde, als WinForms zum ersten Mal herauskam und immer noch eine gute Wahl war. Sie können jede Technik verwenden, die die lang andauernde Arbeit an einem anderen Thread ausführt, aber Sie müssen es für diesen anderen Thread tun.

können Sie von der Asynchron-Muster verwenden, um die Kodierung für den anderen Thread

private async void btnDelete_Click(object sender, EventArgs e) 
{ 
    progressBar1.Visible = true; 
    await Task.Run(() => 
    { 
     // run stored procedure that takes around 5 minutes 
     Task.Delay(10000); 
    }); 
    progressBar1.Visible = false; 
} 
+0

Der Code, den Sie kommentieren, tut nicht das, was Sie sagen, weil die 'Task.Delay()' Methode nicht blockiert. Nun, wenn das OP eine schlechte Frage gestellt hat, in der sie Code zur Verfügung stellen, der nicht wirklich das spezifische Problem reproduziert, das sie haben, und in der Tat haben sie etwas, das _does_ blockiert an der Stelle, wo sie gerade 'Task zeigen. Delay() ', dann wäre Ihr Vorschlag angemessener. Aber dann antwortest du eine andere Frage als gefragt. –

0

Background ist die allgemein akzeptierte Methode zur Durchführung einer solchen Hintergrundarbeit, daher der Name zu vereinfachen; aber für eine primitive "Show für X Zeitraum", könnten Sie einen Timer verwenden, der die verstrichene Zeit seit (in diesem Fall) zuletzt gelöscht hat, um zu sehen, ob es das Steuerelement verstecken sollte (und sich selbst deaktivieren, keine Verwendung ticken, wenn zu tun gibt es nichts)

Etwas wie:.

public partial class ProgressBarSample 
{ 
    TimeSpan pbShowDuration = [blah blah]; 
    DateTime pbShowFrom = DateTime.MinDate; 

    public ProgressBarSample 
    { 
     progressBar1.Style = ProgressBarStyle.Marquee; 
     progressBar1.Visible = false; 
    } 

    private void btnDelete_Click(object sender, EventArgs e) 
    { 
     progressBar1.Visible = true; 
     pbShowFrom = DateTime.Now; 
     timer1.Enabled = true; 
     // run stored procedure that takes around 5 minutes 
    } 

    private void timer1_Tick(object sender, EventArgs e) 
    { 
     if ((DateTime.Now - pbShowFrom) > pbShowDuration) 
     { 
      timer1.Enabled = false; 
      progressBar1.Visible = false;   
     } 
    } 
} 

Aber wie wollen Sie den Fortschrittsbalken aktualisieren?

+1

Die Laufzeit einer gespeicherten Prozedur ist nicht sehr vorhersehbar. Es kann in 2 Minuten auf einem QA-Server mit weniger Daten oder in 10 Minuten abgeschlossen sein, wenn der Server stark ausgelastet ist oder wenn der Server irgendwann mehr Daten hat. Eine passende Zeit für '[blah blah]' einzufügen, ist fast unmöglich. –

+1

@EricJ. Ich gehe einfach durch das, was in der Frage enthalten war, und warum ich dem Beispiel die Beschreibung der "primitiven" Show für die X-Zeit vorangestellt habe ". Offensichtlich wäre die ideale Lösung ein Hintergrundarbeiter oder eine andere Form von Threading; Die meisten Aufgaben, die einen Fortschrittsbalken benötigen, sind nicht sehr vorhersehbar (nicht nur gespeicherte Prozeduren). Selbst das Laden einer Datei wird erheblich variieren, wenn andere Prozesse das Speichermedium/die Bandbreite ausreichend beanspruchen. – Uueerdo

+0

@Uueerdo - das Zelt geht nur in einem Kreis, was ich will. – Missy

0

Mit der neuen Aufgabe, synchronisieren, warten Funktionen in C# haben Sie eine Vielzahl von Optionen. Wenn Sie nichts weiter tun müssen, als den Benutzer wissen zu lassen, dass die Operation ausgeführt wurde, können Sie Ihre Fortschrittsleiste starten und dann eine Aufgabe starten, die Ihren Prozess ausführt. Wenn Sie fertig sind, stoppen Sie die Fortschrittsanzeige. Ich würde persönlich etwas anderes als eine Fortschrittsanzeige setzen. Für mich bedeutet ein Fortschrittsbalken, dass Sie eine begrenzte Zeit haben, um zu warten. Wenn Ihr SP in der Zeit variieren kann, würde ich mit einer Art beschäftigtem Anzeigesymbol oder etwas ähnlichem gehen.

Ich persönlich würde Task.ContinueWith in diesem Fall verwenden.

Dieser MSDN Artikel zeigt eine gute Möglichkeit, damit umzugehen.

https://msdn.microsoft.com/en-us/library/dd270696(v=vs.110).aspx

1

Ohne eine gute Minimal, Complete, and Verifiable code example, die Ihr Problem zuverlässig wiedergibt, ist es unmöglich, mit Sicherheit zu sagen, was das Problem ist. Der von Ihnen gepostete Code funktioniert jedoch nicht. Ihre btnDelete_Click()-Methode setzt die Visible-Eigenschaft auf true, aber setzt dann sofort zurück auf false, weil die Task.Delay()-Methode nicht tatsächlich blockiert.

Wahrscheinlich, was Sie wollen, ist dies:

private async void btnDelete_Click(object sender, EventArgs e) 
{ 
    progressBar1.Visible = true; 
    // run stored procedure that takes around 5 minutes 
    await Task.Delay(10000); 
    progressBar1.Visible = false; 
} 
+1

Das Codebeispiel scheint ausreichend zu sein, um das Problem zu verstehen. Ein komplettes (kompilierbares) WinForms-Sample enthält eine Menge Gepäck, das vom Kernproblem ablenken würde. Er hat Task.Delay als Proxy für einen Aufruf einer gespeicherten Prozedur in seinem echten Code eingefügt, so dass Task.Delay nicht genau das ist, wonach er sucht. –

+2

@EricJ .: Einfügen eines nicht blockierenden Anrufs als Proxy für einen blockierenden Anruf, obwohl plausibel, ist _wrong_ und verhindert, dass jemand tatsächlich weiß, was der Code tut. Das OP muss ein gutes [mcve] bereitstellen, wenn sie eine Antwort wollen, die ihre Frage tatsächlich anspricht. –

0

Hintergrund Arbeiter eine alte Methode, die unter Verwendung von Aufgaben abgelöst wird. Aufgaben haben mehr Funktionalität, können Dinge tun, die Hintergrundarbeiter nicht können und sind viel einfacher zu benutzen.