Как я программно использую ключевое слово “использования” в C#?

dataStream.flatMap(...) возвращает преобразованный поток, но не изменяет исходный dataStream. Вам нужно либо переписать это как

dataStream.flatMap(...).print();

или как

DataStream<Integer> transformed = dataStream.flatMap(...);
transformed.print();
7
задан MrDatabase 8 October 2008 в 23:43
поделиться

3 ответа

using(p = Process.Start(command))

Это скомпилирует, как Process реализации класса IDisposable, однако Вы на самом деле хотите звонить Close метод.
Логика имела бы его что Dispose метод звонил бы Close для Вас, и путем рытья в CLR с помощью отражателя, мы видим, что он действительно на самом деле делает это для нас.Пока все хорошо.

Снова с помощью отражателя, я смотрел на какой Close метод делает - он выпускает базовый собственный дескриптор процесса win32 и очищает некоторые членские переменные. Это (высвобождение внешних средств) точно, что шаблон IDisposable, как предполагается, делает.

Однако я не уверен, является ли это тем, чего Вы хотите достигнуть здесь.

Выпуск базовых дескрипторов просто говорит окнам 'I am no longer interested in tracking this other process'. Ни в каком смысле делает это, на самом деле заставляют другой процесс выходить, или заставлять Ваш процесс ожидать.

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

Если Вы хотите ожидать их для выхода самостоятельно, Вы могли бы использовать p.WaitForExit() - однако это будет только работать, если Вы будете ожидать одного процесса за один раз. Если Вы хотите ожидать их всех одновременно, это становится хитрым.

Обычно Вы использовали бы WaitHandle.WaitAll для этого, но как нет никакого способа получить a WaitHandle объект из a System.Diagnostics.Process, Вы не можете сделать этого (серьезно, wtf Microsoft думали?).

Вы могли вращать поток для каждого процесса и назвать 'WaitForExit в тех потоках, но это - также неправильный способ сделать это.

Вместо этого необходимо использовать p/invoke для доступа к собственному win32 WaitForMultipleObjects функция.

Вот образец (который я протестировал, и на самом деле работает),

[System.Runtime.InteropServices.DllImport( "kernel32.dll" )]
static extern uint WaitForMultipleObjects( uint nCount, IntPtr[] lpHandles, bool bWaitAll, uint dwMilliseconds );

static void Main( string[] args )
{
    var procs = new Process[] {
        Process.Start( @"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 2'" ),
        Process.Start( @"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 3'" ),
        Process.Start( @"C:\Program Files\ruby\bin\ruby.exe", "-e 'sleep 4'" ) };
    // all started asynchronously in the background

    var handles = procs.Select( p => p.Handle ).ToArray();
    WaitForMultipleObjects( (uint)handles.Length, handles, true, uint.MaxValue ); // uint.maxvalue waits forever

}
15
ответ дан 6 December 2019 в 10:55
поделиться

Для ссылки: ключевое слово использования для объектов IDisposable:

using(Writer writer = new Writer())
{
    writer.Write("Hello");
}

просто синтаксис компилятора. То, во что это компилирует вниз:

Writer writer = null;
try
{
    writer = new Writer();
    writer.Write("Hello");
}
finally
{
    if( writer != null)
    {
        ((IDisposable)writer).Dispose();
    }
}

using немного лучше, так как компилятор препятствует тому, чтобы Вы повторно присвоили ссылку устройства записи в блоке использования.

Инструкции по платформе Раздел 9.3.1 p. 256 состояний:

РАССМОТРИТЕ обеспечение метода Близко (), в дополнение к Расположению (), если близко стандартная терминология в области.


В Вашем примере кода внешняя выгода попытки является ненужной (см. выше).

Используя, вероятно, не делает то, что Вы хотите здесь, с тех пор Располагают (), назван как только p выходит из объема. Это не закрывает (протестированный) процесс.

Процессы независимы, поэтому если Вы не звоните p.WaitForExit() они вылетают и делают свою собственную вещь, абсолютно независимую от Вашей программы.

Парадоксально, для Процесса, Близко () только высвобождает средства, но оставляет выполнение программы. CloseMainWindow () может работать на некоторые процессы и Уничтожить (), будет работать для уничтожения любого процесса. Оба CloseMainWindow () и Уничтожают (), может выдать исключения, так быть осторожным, если Вы используете их в наконец блок.

В заключение, вот некоторый код, который ожидает процессов для окончания, но не избавляется от процессов, когда исключение происходит. Я не говорю, что это лучше, чем Orion Edwards, просто отличается.

List<System.Diagnostics.Process> processList = new List<System.Diagnostics.Process>();

try
{
    foreach (string command in Commands)
    {
        processList.Add(System.Diagnostics.Process.Start(command));
    }

    // loop until all spawned processes Exit normally.
    while (processList.Any())
    {
        System.Threading.Thread.Sleep(1000); // wait and see.
        List<System.Diagnostics.Process> finished = (from o in processList
                                                     where o.HasExited
                                                     select o).ToList();

        processList = processList.Except(finished).ToList();
        foreach (var p in finished)
        {
            // could inspect exit code and exit time.
            // note many properties are unavailable after process exits
            p.Close();
        }
    }
}
catch (Exception ex)
{
    // log the exception
    throw;
}
finally
{
    foreach (var p in processList)
    {
        if (p != null)
        {
            //if (!p.HasExited)
            // processes will still be running
            // but CloseMainWindow() or Kill() can throw exceptions
            p.Dispose();
        }

    }
}

Я не беспокоился, Уничтожают () 'луг от процессов, потому что код запускается, становятся еще более ужасными. Прочитайте документацию MSDN для получения дополнительной информации.

3
ответ дан 6 December 2019 в 10:55
поделиться
try
{
   foreach(string command in S) // command is something like "c:\a.exe"
   {
      using(p = Process.Start(command))
      {
        // I literally put nothing in here.
      }

    } 
}
catch (Exception e)
{
    // notify of process failure
}

Причина это работает, состоит в том, потому что, когда исключение происходит, переменная p падения из объема и таким образом это, Располагают метод, назван, который закрывается, процесс состоит в том, как это пошло бы. Кроме того, я думал бы, что Вы захотите кружить поток для каждой команды, а не ожидать исполняемого файла для окончания прежде, чем перейти к следующему.

0
ответ дан 6 December 2019 в 10:55
поделиться
Другие вопросы по тегам:

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