Windows Forms, BackgroundWorker

Windows Forms, BackgroundWorker
JK
  • Rejestracja:ponad 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:55
0

Więcej niż jeden obiekt backgroundWorker (dzialaja w petli) modufikuja zmienną zadeklarowaną jako prywatna zmienna formy.
Domyślam się, że należałoby tutaj zastosować jakąś synchronizacje.
Wskazówki, jak zrobić to prawdiłowo ?

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
1

jeśli jest to zmienna typu prostego (int, double, ...) to nie ma takiej potrzeby. Jeśli nie to możesz użyć lock, mutex, samphor - w googlach naprawdę jest to dobrze opisane


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
JK
  • Rejestracja:ponad 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:55
0

Czyli obiekty backgroundWorker są już w jakiś sposób zabezpieczone przed potencjalną chęcią odwołania się do danej zmiennej przez więcej niż jeden obiekt tego typu jednocześnie ? A może jest to po prostu niegroźne ?

abrakadaber
abrakadaber
  • Rejestracja:ponad 12 lat
  • Ostatnio:8 miesięcy
  • Postów:6610
0

operacje na zmiennych prostych są niegroźne, co innego np. obiekty, tablice, struktury czy ciągi znaków


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.
Azarien
są niegroźne aż ci program eksploduje po godzinie pracy. rzeczywiste przypadki niegroźności są bardzo ograniczone. wypadałoby choćby o volatile wtedy pamiętać.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 7 godzin
2

Czyli obiekty backgroundWorker są już w jakiś sposób zabezpieczone przed potencjalną chęcią odwołania się do danej zmiennej przez więcej niż jeden obiekt tego typu jednocześnie

Nie, nie są. Chodzi o to, że w niektórych ograniczonych przypadkach jest to niegroźne.

Problem nie jest w „potencjalnej chęci odwołania się do zmiennej jednocześnie”, bo to zawsze działa, ale w tym, jakie to może mieć konsekwencje.

Na przykład, jeśli jeden wątek czyta zmienną, a drugi zapisuje, to wystarczy że zmienna będzie volatile i nie trzeba dodatkowej synchronizacji.

Przy czym „zapisuje” należy rozumieć ściśle. x++ to nie tylko zapis, ale i odczyt: x=x+1.

Jeśli kilka wątków robi takie x=x+1, to jeden może odczytać zmienną, drugi w tym samym czasie odczytać zmienną, pierwszy zwiększy o jeden, zapisze, drugi zwiększy o jeden oryginalną wartość, zapisze, i w rezultacie x zwiększył się o 1 zamiast o 2.

Wszystko więc zależy od tego jak wygląda kod.
Dla pewności używaj właściwych mechanizmów synchronizacji. Oprócz locków i mutexów, do operacji na pojedynczych zmiennych pod Windows masz funkcje InterlockedExchange i okoliczne, w .NET klasę Interlocked.

JK
  • Rejestracja:ponad 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:55
0

Czyli jeśli w 'formie' deklaruje tablicę:

Kopiuj
array<int> ^Diods = gcnew array <int>(6);

To utworzenie w wątku nowej zmiennej tego samego typu i wywołanie funkcji Exchange:

Kopiuj
array<int> ^ExDiods = gcnew array <int>(6);
Interlocked::Exchange(Diods, ExDiods);

I posługiwanie się w wątku zmienną ExDiods jest wystarczające?

edytowany 1x, ostatnio: JeloneK
Azarien
najpierw musiałbyś ją wypełnić, a dopiero potem exchange. bo co z tego że zrobisz wymianę tablicy atomowo, skoro potem ją modyfikujesz.
JK
  • Rejestracja:ponad 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:55
0

Rzeczywiście coś pomieszałem.
Robię więc tak, że w wątku, w którym modyfikuję wartości Diods, tworzę ExDiods i ExDiods modyfikuję, a następnie komendą Exchange "podmieniam" (jeśli można to tak nazwać) i wygląda na to, że działa poprawnie.

Co natomiast z synchronizacją w wątku, w którym tylko odczytuję wartości z Diods i przepisuję je do innej tablicy. Czy tam również synchronizacja jest potzebna ?

0

Hej, przeanalizuj sobie jak można wykorzystać sekcję krytyczną.

Kopiuj
 
#include <windows.h>

class CSomeClass
{
public:
    CSomeClass()
    {
        InitializeCriticalSection(&m_csCriticalSection);
    }
    ~CSomeClass()
    {
        DeleteCriticalSection(&m_csCriticalSection);
    }
    
    int getIntSave(int a_iIndex)
    {
        int iRetval;
        EnterCriticalSection(&m_csCriticalSection);
        iRetval = m_aGlobalArray[a_iIndex];
        LeaveCriticalSection(&m_csCriticalSection);
        return iRetval;
    }
    
private:
    int m_aGlobalArray[5] = {0,1,2,3,4};
    CRITICAL_SECTION m_csCriticalSection;
};
D1
Hmm, można pisać nie będąc zalogowanym. Dobrze wiedzieć :)
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 7 godzin
0

Diods

Co to jest “diods”?

Co natomiast z synchronizacją w wątku, w którym tylko odczytuję wartości z Diods i przepisuję je do innej tablicy. Czy tam również synchronizacja jest potzebna

Jeśli w tym wątku tylko odczytujesz, a w tamtym podmieniasz wypełnioną już tablicę, to wątek odczytujący odczyta albo całą nową, albo całą starą - czyli dobrze. Synchronizacja służy zapobieganiu odczytu danych częściowo nowych a częściowo starych.

JK
  • Rejestracja:ponad 9 lat
  • Ostatnio:prawie 9 lat
  • Postów:55
0

Ostatecznie ograniczyłem się tylko do jednego wątku dodatkowego, ale zmienne

Kopiuj
 array<int> ^Diods = gcnew array <int>(6);

odpowiadające za przechowywanie danych, które mają być przekazywane do mikrokontrolera ciagle sa deklarowane w klasie "forma", dlatego ze zmienne te moga byc rowniez modyfikowane poprzez bezposrednie zdarzenia wywolywane w formie np. nacisniecie przycisku, przesuniecie suwaka, etc. Dlatego tez uznalem, ze synchronizacja jednak byc powinna.

W watku najpierw pobieram dane, nastepnie w oparciu o te dane i dane pochodzace z formy modyfikuje tablice:

Kopiuj
 array<int> ^ExDiods_K = gcnew array <int>(6);

ktora po przeprowadzeniu modyfikacji "kopiuje" do zmiennej 'Diods'

Kopiuj
 Interlocked::Exchange(Diods, ExDiods_K);

Nastepnie "tworze kopie" zmiennej Diods:

Kopiuj
Interlocked::Exchange(ExDiods_T, Diods); 

którą to, po odpowiednim przekonwertowaniu wysyłam do mikrokontrolera.

Robię to w ten sposób, ponieważ w miedzyczasie moze zostac wywołane zdarzenie, które rowniez będzie zmieniało wartości elementów tablicy 'Diods'

Czy ma to sens ? ^^

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.