Anulowanie wątków stworzonych przez Parallel.For

0

Witam. Pisze aplikacje sluzaca do rozwiazywania pewnego problemu optymalizacyjnego. Mam kilka zaimplementowanych algorytmow oraz gui (WinForms), w ktorym odpalam kilka z tych algorytmow roznolegle, one z kolei updatuja progress bary itd. Wykorzystuje do tego metode Parallel.For, ale ma ona jedna wade. Mianowicie przy cancelowaniu Fora, taski ktore juz sa "w uzyciu" kontunuuja swoje dzialanie, co mi nie bardzo odpowiada. Chodzi o to, ze skoro znalezione rozwiazanie satysfakcjonuje uzytkownika, powinien on miec mozliwosc anulowania wszystkich obliczen i zwolnienia CPU. Moj kod wyglada w uproszczeniu tak:

czesc zwiazana z gui:

Task.Factory.StartNew(() =>{    Parallel.For(0, iterations, i =>    
    {        
        Worker worker = new Worker(ReportProgress, guiHandler);       
        worker.run(i);    
    });
});

metoda optymalizujaca (osobna klasa):

public Worker(StatusReporter reportProgress, guiHandler guiHandler)    
{        
    this._guiHandler = guiHandler;       
    this._reportProgress = reportProgress;   
 }    
public void run(Object threadContext)    
{        
    int threadIndex = (int)threadContext;        
    int seed;       
    lock (syncLock)        
    {            
        seed = rnd.Next(100, 500);        
    }        
    _guiHandler("create", threadIndex, seed);//updating gui        
    for (int i = 0; i < seed; i++)       
    {            
        System.Threading.Thread.Sleep(100);            
        _reportProgress(threadIndex, i); //updating progress bars        
    }        
    _guiHandler("delete", threadIndex, seed);//updating gui    
}

Potrzebuje pomocy w znalezieniu jakiegos fajnego mechanizmu aby powiadomic metody run() o tym, ze uzytkownik nacisnal Cancel i trzeba skonczyc działanie

0

Mianowicie przy cancelowaniu
Nie pokazałeś jak cancelujesz fora.

Potrzebuje pomocy w znalezieniu jakiegos fajnego mechanizmu aby powiadomic metody run() o tym, ze uzytkownik nacisnal Cancel i trzeba skonczyc działanie

for (int i = 0; i < seed && !cancelled; i++)  

Jeśli cancelled będziesz ustawiać tylko w jednym miejscu, to myślę że volatile bool cancelled; powinno być bezpieczne.

Ale generalnie ten kod jest brzydki...

PS. Jest też coś takiego jak CancellationToken. Poszukaj.

0

Dzieki za odpowiedz, ale te sposoby juz sprawdzilem. Rezultat byl taki, ze petla zostaje przerwana, ale watki juz stworzone przez Fora dalej sie wukonuja, a chodzi mi wlasnie o to, zeby te watki jakos przerwac. A kod byc moze jest brzydki, powstal na szybko, zeby zobrazowac sam schemat :)

0

A tak próbowałeś ?

            // i is the iteration variable. loopState is a  
            // compiler-generated ParallelLoopState
            Parallel.For(0, source.Length, (i, loopState) =>
            {
                // Take the first 100 values that are retrieved 
                // from anywhere in the source. 
                if (i < 100)
                {
                    // Accessing shared object on each iteration 
                    // is not efficient. See remarks. 
                    double d = Compute(source[i]);
                    results.Push(d);
                }
                else
                {
                    loopState.Stop();
                    return;
                }

            } // Close lambda expression.
            ); // Close Parallel.For

Source: http://msdn.microsoft.com/en-us/library/dd460721.aspx

0

Takie podejscie tez mnie niestety nie urządza, dlatego, że For przerywa dzialanie wtedy, kiedy licznik wowołań wątków osiagnie 100 - po prostu petla przestanie tworzyc watki, ale te, ktore juz dzialaja beda dzialaly dalej. A mi wlasnie chodzi o to, zeby jakos zastopowac watki stworzone przez Fora przy nacisnieciu jakiegos przycisku, petla nie wie wczesniej kiedy bedzie przerwana

1 użytkowników online, w tym zalogowanych: 0, gości: 1