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 ?
- Rejestracja:ponad 9 lat
- Ostatnio:ponad 8 lat
- Postów:55

- Rejestracja:ponad 12 lat
- Ostatnio:8 miesięcy
- Postów:6610
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

- Rejestracja:ponad 12 lat
- Ostatnio:8 miesięcy
- Postów:6610
operacje na zmiennych prostych są niegroźne, co innego np. obiekty, tablice, struktury czy ciągi znaków


- Rejestracja:ponad 21 lat
- Ostatnio:4 minuty
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.
- Rejestracja:ponad 9 lat
- Ostatnio:ponad 8 lat
- Postów:55
Czyli jeśli w 'formie' deklaruje tablicę:
array<int> ^Diods = gcnew array <int>(6);
To utworzenie w wątku nowej zmiennej tego samego typu i wywołanie funkcji Exchange:
array<int> ^ExDiods = gcnew array <int>(6);
Interlocked::Exchange(Diods, ExDiods);
I posługiwanie się w wątku zmienną ExDiods jest wystarczające?

- Rejestracja:ponad 9 lat
- Ostatnio:ponad 8 lat
- Postów:55
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 ?
Hej, przeanalizuj sobie jak można wykorzystać sekcję krytyczną.
#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;
};

- Rejestracja:ponad 21 lat
- Ostatnio:4 minuty
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.
- Rejestracja:ponad 9 lat
- Ostatnio:ponad 8 lat
- Postów:55
Ostatecznie ograniczyłem się tylko do jednego wątku dodatkowego, ale zmienne
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:
array<int> ^ExDiods_K = gcnew array <int>(6);
ktora po przeprowadzeniu modyfikacji "kopiuje" do zmiennej 'Diods'
Interlocked::Exchange(Diods, ExDiods_K);
Nastepnie "tworze kopie" zmiennej Diods:
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 ? ^^