будьте уведомлены, когда все фоновые потоки пула потоков будут закончены

Cut Paste

Cut Cut

Sub CutPaste()

    Const cSheet As Variant = "Sheet1"      ' Worksheet Name/Index
    Const cFirstS As Variant = "E"          ' Source First Column Letter/Number
    Const cLastS As Variant = "O"           ' Source Last Column Letter/Number

    Const cFirstT As Variant = "D"          ' Target First Column Letter/Number

    Const cFirstRow As Long = 1             ' First Row Number
    Const cCriteria As Variant = "B"        ' Criteria Column Letter/Number
    Const cStrCriteria As String = "Plan"   ' Criteria String

    Dim lastRow As Long   ' Last Row Number
    Dim i As Long         ' Row Counter

    With ThisWorkbook.Worksheets(cSheet)
        lastRow = .Cells(.Rows.Count, cFirstS).End(xlUp).Row
        For i = cFirstRow To lastRow
            If .Cells(i, cCriteria) = cStrCriteria Then
                .Range(.Cells(i, cFirstS), .Cells(i, cLastS)).Cut _
                        Destination:=.Cells(i, cFirstT)
            End If
        Next
    End With

End Sub

Копировать ClearContents Version

Sub CopyClearContents()

    Const cSheet As Variant = "Sheet1"      ' Worksheet Name/Index
    Const cFirstS As Variant = "E"          ' Source First Column Letter/Number
    Const cLastS As Variant = "O"           ' Source Last Column Letter/Number

    Const cFirstT As Variant = "D"          ' Target First Column Letter/Number

    Const cFirstRow As Long = 1             ' First Row Number
    Const cCriteria As Variant = "B"        ' Criteria Column Letter/Number
    Const cStrCriteria As String = "Plan"   ' Criteria String

    Dim lastRow As Long   ' Last Row Number
    Dim i As Long         ' Row Counter

    With ThisWorkbook.Worksheets(cSheet)
        lastRow = .Cells(.Rows.Count, cFirstS).End(xlUp).Row
        For i = cFirstRow To lastRow
            If .Cells(i, cCriteria) = cStrCriteria Then
                .Range(.Cells(i, cFirstS), .Cells(i, cLastS)).Copy _
                        Destination:=.Cells(i, cFirstT)
                .Cells(i, cLastS).ClearContents
            End If
        Next
    End With

End Sub
10
задан Valentin Vasilyev 21 July 2015 в 06:54
поделиться

6 ответов

Постепенное уменьшение переменной (между потоками) немного опасно, если не покончили Interlocked.Decrement, но тот подход должен быть прекрасным, если у Вас есть последний поток (т.е. когда это добирается для обнуления), генерируют событие. Обратите внимание, что это должно было бы быть в "наконец" блок, чтобы не проигрывать, это в случае исключений (плюс Вы не хотят уничтожать процесс).

В "Параллельных Расширениях" (или с.NET 4.0), Вы могли бы также посмотреть на Parallel.ForEach опции здесь..., которые могли бы быть другим способом получить все сделанное как блок. Не имея необходимость наблюдать их всех вручную.

11
ответ дан 3 December 2019 в 18:36
поделиться

Если его не больше чем 64 Потока для ожидания на можно использовать WaitHandle. Метод WaitAll как это:

List<WaitHandle> events = new List<WaitHandle>();
for (int i = 0; i < 64; i++)
{
    ManualResetEvent mre = new ManualResetEvent(false);
    ThreadPool.QueueUserWorkItem(
        delegate(object o)
        {
            Thread.Sleep(TimeSpan.FromMinutes(1));
            ((ManualResetEvent)o).Set();
        },mre);
    events.Add(mre);
}
WaitHandle.WaitAll(events.ToArray());

Выполнение будет ожидать, пока все ManualResetEvents не установлены, альтернативно, можно использовать метод WaitAny.

Методы WaitAny и WaitAll заблокируют выполнение, но можно просто использовать список или словарь ManualResetEvents, связанного с задачей, которая является икрой для более позднего определения, если поток сделан все же.

3
ответ дан 3 December 2019 в 18:36
поделиться

Существует, не встроенный способ сделать это в данный момент - я нахожу это одной из самых больших болей об использовании потоков пула.

Как Marc говорит, это - вид материала, который фиксируется в параллельных Расширениях/.NET 4.0.

2
ответ дан 3 December 2019 в 18:36
поделиться

Не могли Вы давать каждому потоку отличный ManualResetEvent и каждый устанавливать событие при выполнении. Затем в основном потоке можно ожидать на всех событиях, переданных в.

1
ответ дан 3 December 2019 в 18:36
поделиться

Решение Marc является лучшим, если Вы просто хотите знать, когда все задания закончены и не нужны в более прекрасной информации, чем тот (как, кажется, Ваш случай).

Если бы Вы хотели, чтобы некоторый поток породил задания и некоторый другой поток к получить уведомления, то Вы могли использовать WaitHandle. Код намного длиннее.

    int length = 10;
    ManualResetEvent[] waits = new ManualResetEvent[length];
    for ( int i = 0; i < length; i++ ) {
        waits[i] = new ManualResetEvent( false );
        ThreadPool.QueueUserWorkItem( (obj) => {
            try {

            } finally {
                waits[i].Set();
            }
        } );
    }

    for ( int i = 0; i < length; i++ ) {
        if ( !waits[i].WaitOne() )
            break;
    }

Метод WaitOne, как записано, всегда возвращает true, но я записал это как этот, чтобы заставить Вас помнить, что некоторые перегрузки берут Тайм-аут в качестве аргумента.

0
ответ дан 3 December 2019 в 18:36
поделиться

Что относительно того, чтобы использовать Семафор, и установленный предел к нему так же как Ваш пул потоков. Имейте метод, чтобы выбрать Семафор, быть названными, когда Вы запускаете свой поток, выпускаете его, когда Ваш конец потока и генерирует событие при приведении в рабочее состояние всего Семафора.

0
ответ дан 3 December 2019 в 18:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: