ThreadPool Асинхронизированные потоки в том же методе - PullRequest
0 голосов
/ 13 апреля 2011

У меня есть вопрос относительно использования ThreadPool в данный момент.После того, как я запускаю простой код ниже.Я получаю результат:

  • ID: 6 -> A
  • ID: 13 -> A
  • ID: 6 -> 2A
  • ID: 12 -> A
  • ID: 13 -> 2A
  • ID: 15 -> A
  • ID: 6 -> 3A
  • ID: 12 -> 2A
  • ID: 14 ​​-> A
  • ID: 13 -> 3A

(это идетна ...) Вот мой код:

static void Main(string[] args)
{
    Program p = new Program();
    p.Start();
    Console.ReadLine();
}

private void Start()
{
    System.Timers.Timer senderTimer;
    senderTimer = new System.Timers.Timer();
    senderTimer.Elapsed += new System.Timers.ElapsedEventHandler(SenderTimer);
    senderTimer.Interval = 500;
    senderTimer.Enabled = true;
}

private void SenderTimer(object Source, ElapsedEventArgs e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(Foo));
}

private void Foo(object state)
{
    string[] array = new string[] { "A", "2A", "3A", "4A", "5A", "6A", "7A", "8A", "9A", "10A" };

    for (int i = 0; i < array.Length; i++)
    {
        Trace.WriteLine("ID : " + Thread.CurrentThread.GetHashCode() + " --> " + array[i]);
        Thread.Sleep(1000); // Here I have a DB Operation, so i make it sleep
    }
}

Что мне нужно получить в результате, так это то, что несколько потоков делают одну и ту же вещь синхронизированной.Вот результат, который я должен получить: Надеюсь, я объяснил ясно.Есть ли способ сделать это?

  • ID: 6 -> A
  • ID: 13 -> 2A
  • ID: 6 -> 3A
  • ID: 12 -> 4A
  • ID: 13 -> 5A
  • ID: 15 -> 6A
  • ID: 6 -> 7A
  • ID: 12 -> 8A
  • ID: 14 ​​-> 9A
  • ID: 13 -> 10A

Ценю любую помощь.Большое спасибо.

Ответы [ 2 ]

1 голос
/ 13 апреля 2011

Если вы хотите форсировать порядок обработки, то нет смысла делать его многопоточным, так как каждый поток все равно будет ожидать предыдущий.

Если вы хотите выполнить обработку параллельно, а затем расположить результаты в том же порядке, в котором они были получены, вы можете использовать

        string[] array = new string[] { "A", "2A", "3A", "4A", "5A", "6A", "7A", "8A", "9A", "10A" };
        var results = array.AsParallel().Select((item, i) =>
        new
        {
            Index = i,
            Result = ProcessItem(item)
        })
        .OrderBy(x => x.Index)
        .Select(i=>i.Result)
        .ToList();
0 голосов
/ 13 апреля 2011

У вас должен быть массив чисел для печати вне вашей функции Foo.Если он внутри, каждый поток будет пытаться обработать полный список, но это не то, что вы хотите (насколько я могу судить).

Вы хотите создать новую функцию, скажем GetNextItemToProcessэто вернет следующий элемент в массиве, который еще не был обработан.Затем в вашей функции Foo вызовите что-то вроде

lock(this)
{
   string nextItem = GetNextItemToProcess();
   Trace.WriteLine("ID : " + Thread.CurrentThread.GetHashCode() + " --> " + nextItem );
}

Поскольку каждый поток должен убедиться, что он правильно захватывает следующий элемент, вам необходимо заблокировать его.ВАЖНОЕ ПРИМЕЧАНИЕ: блокировка всей функции, гарантируя, что вы хотите, не подходит для многопоточности.С этим методом он мог бы быть последовательным.Потоки действительно принесут вам пользу, если каждый элемент работы может быть выполнен в произвольном порядке, что здесь не так.Если вам действительно нужен выходной сигнал «A, 2A, 3A», вам лучше делать это последовательно.Если это может быть «2A, A, 3A» или случайный порядок, в котором каждый элемент должен появиться ровно один раз, то многопоточность - это то, что вам нужно.

...