-1

У меня странная ошибка в моем текущем проекте. Вот почему у меня есть два вопроса:Задачи TPL и ReaderWriterLockSlim

1) Почему это происходит?
2) Как это решить?

Некоторые дополнительная информация: Я бегу это на системе с процессором QuadCore (Intel Core2Quad Q9650)

У меня есть функция «DoSomething()», который может быть вызван из нескольких потоков одновременно:

public class SingletonClass  
{ 

    // Singleton 
    public static SingletonClass Instance 
    { 
     get { return _instance ?? (_instance = new SingletonClass()); } 
    } 

    private readonly ReaderWriterLockSlim _workLock = new ReaderWriterLockSlim(); 
    private bool _isWorkDone = false; 

    // bool returns true for "Inner Task executed" and false for "Inner Task had been executed earlier" 
    public bool DoSomething() 
    { 
     // workaround to fix: Thread.Sleep(50); 
     _workLock.EnterWriteLock(); 
     try 
     { 
      if (!_isWorkDone) 
      { 
       Task.Factory.StartNew(DoWork()); 
       _isWorkDone = true; 
       return true; 
      } 

      return false; 
     } 
     finally 
     { 
      _workLock.ExitWriteLock(); 
     } 
    } 
} 

для того, чтобы проверить, если эта функция работает, я использовал TPL для создания нескольких задач, вызывающими эту функцию почти Simultaniously:

for (int i = 0; i < 10; i += 1) 
{ 
    Task.Factory.StartNew(() => 
    { 
     bool success = DoSomething(); 
     Console.WriteLine(success); 
    }); 
} 

Я ожидал получить такой вывод:

истинное, ложное, ложное, ....

Но что я получил это:

правда, правда, правда, true, false, false ....

Запомнить:
1) Почему?
2) Как решить?

EDIT: Я добавил образец-проект: [УДАЛИТЬ - Проблема решена]

+0

есть (конечно) новое другие функции, используя EnterReadLock. Но дело не в этом. Вместо этого я попытался использовать lock (_lockObject), но получил тот же неожиданный вывод. – myst3rium

+0

Я попытался воспроизвести это, и я получу ожидаемый результат. –

+0

Могу я спросить, какой у вас процессор? Если я добавлю Thread.Sleep (50) до '_workLock.EnterWriteLock();' он работал для меня. Но это обходное решение в лучшем случае. – myst3rium

ответ

0

Ни в коем случае, проблема не в замке, а в создании Singleton!

public static Dll Instance 
{ 
    get { return _INSTANCE ?? (_INSTANCE = new Dll()); } 
} 

Вышеуказанное не защищено блокировкой => вы получаете 4 разных экземпляра! Четыре разных замка!

private void CreateThreadsToAccess() 
{ 
    Task[] tasks = new Task[10]; 
    for (int i = 0; i < tasks.Length; i += 1) 
    { 
     tasks[i] = Task.Factory.StartNew(() => 
     { 
     // here you get four different instances 
      bool success = Dll.Instance.DoSomething(); 
      Console.WriteLine(success); 
     }); 
    } 

    Task.WaitAll(tasks); 

    Console.WriteLine("Press any key to exit"); 
    Console.ReadKey(); 
} 

Как исправить:

private static readonly object mylock = new object(); 
public static Dll Instance 
{ 
    get 
    { 
     if (_INSTANCE == null) 
     { 
      lock (mylock) 
      { 
       if (_INSTANCE == null) 
       { 
       _INSTANCE = new Dll(); 
       } 
      } 
     } 
     return _INSTANCE; 
    } 
} 
+0

Большое спасибо. Я думаю, что я должен сделать перерыв ^^ – myst3rium

+0

BTW: Посмотрите на этот вопрос: http://stackoverflow.com/questions/12316406/thread-safe-c-sharp-singleton-pattern – firda

Смежные вопросы