Question

J'ai deux listes de sélection, une maîtresse et l'autre enfant. Lorsque l'index change sur le gabarit principal, la liste déroulante enfant est correctement remplie avec les enregistrements associés au gabarit. Mon problème survient lorsqu'un maître met beaucoup de temps à récupérer tous les enregistrements et, avant de le faire, un utilisateur clique sur un autre maître qui prend moins de temps à remplir. En fin de compte, le maître qui prenait plus de temps remplit la zone de liste des enfants, même si l'utilisateur n'en fait plus partie.

J'utilise les threads BackgroundWorker pour le remplissage.

bw_LoadAll.DoWork += new DoWorkEventHandler(bg_LoadAllWork);
bw_LoadAll.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_LoadAllWorkCompleted);
bw_LoadAll.WorkerSupportsCancellation = true;

Je me suis abonné à l'événement SelectedIndexChanged pour le maître et je règle l'équivalent annulé sur true:

bw_LoadAll.CancelAsync();

Voici le code de la méthode DoWork:

List<object> s = Repository.Instance().LoadAll();
if (!bw_LoadAll.CancellationPending) {
    e.Result = s;
} else {
    e.Cancel = true;
}

Mais pour une raison quelconque, le code du travailleur terminé continue à être appelé. Voici le code rempli par le travailleur:

if (!e.Cancelled) {
    ddl.DataSource = e.Result;
    ddl.DisplayMember = "QuickName";
    ddl.ValueMember = "ID";
}

Y a-t-il autre chose que je dois faire pour annuler le retour de ce fil?

Était-ce utile?

La solution

Votre méthode, bg_LoadAllWork, doit être définie comme suit:

void bg_LoadAllWork(object sender, DoWorkEventArgs e)
{
    // Do your work here...
} 

À l'intérieur de bg_LoadAllWork, vous devez vérifier e.CancellationPending et, le cas échéant, définissez e.Cancel = true;

.

Cette dernière partie est importante - si vous ne définissez jamais e.Cancel, votre " e.Cancelled " ne sera jamais égal à vrai. L’appel de CancelAsync n’annule pas réellement quoi que ce soit, c’est plus comme "Demander que le travail en arrière-plan s’annule lui-même". - vous devez mettre en place la logique permettant l'annulation.

Autres conseils

De CodeProject dans votre fonction do_work, vous devez vérifier Annulation en cours sur le thread de travail définit ensuite la variable DoWorkEventArgs.Cancel sur true.

Cela fait longtemps que je n'ai pas utilisé BackgroundWorker, mais si je me souviens bien, lorsque vous appelez bw_LoadAll.CancelAsync , il n'y a pas d'avortement réel de votre méthode LoadAllWork . sauf si LoadAllWork vérifie bw_LoadAll.CancelationPending .

Confirmé par http://msdn.microsoft .com / fr-us / library / system.componentmodel.backgroundworker.cancelasync.aspx : "CancelAsync envoie une demande pour mettre fin à l'opération en arrière-plan en attente et définit la propriété CancellationPending sur true.

Lorsque vous appelez CancelAsync, votre méthode de travail a l'occasion d'arrêter son exécution et de quitter. Le code de l'opérateur doit vérifier périodiquement la propriété CancellationPending pour voir si elle a été définie sur true. "

Ainsi, dans votre gestionnaire d'événements SelectedIndexChanged, lorsque vous appelez bw_LoadAll.CancelAsync () , la définition de bw_LoadAll.CancelationPending est définie sur true, mais n'annule pas réellement le Méthode LoadAllWork . Le chargeur lent va encore finir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top