Есть ли хороший метод в C# для выдачи исключения на данном потоке

В дополнение к предоставленным ответам есть подробное объяснение использования платформы Android в Википедии ( permalink ).

Эта таблица будет дают вам преимущество Android API vs Version.

11
задан fryguybob 4 September 2008 в 20:03
поделиться

8 ответов

Это не хорошая идея

Эта статья говорит о библиотеке тайм-аута рубина. который выдает исключения через потоки.

Это объясняет, как выполнение такой вещи существенно повреждается. Это только повреждается в рубине, это повреждается где угодно, который выдает исключения через потоки.

Короче говоря что может (и делать), происходят, это:

ThreadA:

At some random time, throw an exception on thread B:

ThreadB:

try {
    //do stuff
} finally {
    CloseResourceOne();
    // ThreadA's exception gets thrown NOW, in the middle 
    // of our finally block and resource two NEVER gets closed.
    // Obviously this is BAD, and the only way to stop is to NOT throw
    // exceptions across threads
    CloseResourceTwo();
}

Ваша 'периодическая проверка' пример прекрасна, поскольку Вы на самом деле не выдаете исключения через потоки.
Вы просто устанавливаете флаг, который говорит, "выдают исключение в следующий раз, когда Вы смотрите на этот флаг", который прекрасен, поскольку он не страдает от, "может быть брошен посреди Вашей выгоды или наконец блока" проблема.
Однако, если Вы собираетесь сделать это, можно также просто устанавливать флаг "exitnow" и использовать это и сохранять себя стычка создания объекта исключения. Энергозависимый bool будет работать просто великолепно для этого.

10
ответ дан 3 December 2019 в 05:14
поделиться

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

Исключением является механизм, используемый, чтобы сигнализировать, что процесс испытал что-то исключительное, с которым это не может иметь дело. Необходимо постараться не писать код так, чтобы исключение использовалось, чтобы сигнализировать, что что-то еще испытало что-то исключительное.

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

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

Используйте объекты-события или подобный, чтобы сказать потоку прерывать свою обработку, это - лучший способ.

10
ответ дан 3 December 2019 в 05:14
поделиться

При исследовании другой проблемы я столкнулся с этой статьей, которая напомнила мне о вопросе:

Достигание глубин ThreadAbortException с помощью Ротора

Это показывает циркуляции, что.NET идет до Потока реализации. Аварийное прекращение работы () - по-видимому, любое другое исключение перекрестного потока должно было бы быть подобным. (Yeech!)

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

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

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

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

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

Как другие, я не уверен, что это - такая хорошая идея, но если Вы действительно хотите сделать это, затем можно создать подкласс SynchronizationContext, который позволяет отправлять и отправлять делегатов в целевом потоке (если это - поток WinForms, работа сделана для Вас как таковой, подкласс уже существует). Целевой поток должен будет реализовать своего рода насос сообщения, эквивалентный хотя, для приема делегатов.

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

@Orion Edwards

Я беру Вашу точку об исключении, добавляемом наконец блок.

Однако я думаю, что существует путь - использование еще одного потока - использования этой идеи исключения поскольку прерывание.

Поток A:

At some random time, throw an exception on thread C:

Поток B:

try {
    Signal thread C that exceptions may be thrown
    //do stuff, without needing to check exit conditions
    Signal thread C that exceptions may no longer be thrown
}
catch {
    // exception/interrupt occurred handle...
}
finally {
    // ...and clean up
    CloseResourceOne();
    CloseResourceTwo();
}

Поток C:

 while(thread-B-wants-exceptions) {
        try {
            Thread.Sleep(1) 
        }
        catch {
            // exception was thrown...
            if Thread B still wants to handle exceptions
                throw-in-B
        }
    }

Или это просто глупо?

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

То, что говорит Орион Эдвардс, не совсем верно: это не "единственный" способ.

// Очевидно, что это плохо, и единственный способ остановить это - НЕ бросать
// исключения в потоках

Использование CER (Constrained Execution Regions) в C# позволяет вам освобождать ресурсы как атомарную операцию, защищая ваш код от межпотоковых исключений. Эта техника используется несколькими классами .NET Framework, которые работают с родным API Windows, где неосвобожденный хэндл может привести к утечке памяти.

См. http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.prepareconstrainedregions.aspx

В следующем примере показано, как надежно установить хэндлы с помощью метода PrepareConstrainedRegions. Чтобы надежно установить хэндл на указанный ранее существующий хэндл, необходимо убедиться, что выделение собственного хэндла и последующая запись этого хэндла в объект SafeHandle являются атомарными. Любой сбой между этими операциями (например, прерывание потока или исключение из памяти) приведет к утечке родного дескриптора. Вы можете использовать метод PrepareConstrainedRegions, чтобы убедиться, что хэндл не будет утечен.

Как просто:

public MySafeHandle AllocateHandle()
{
    // Allocate SafeHandle first to avoid failure later.
    MySafeHandle sh = new MySafeHandle();

    RuntimeHelpers.PrepareConstrainedRegions();
    try { }
    finally  // this finally block is atomic an uninterruptible by inter-thread exceptions
    {
        MyStruct myStruct = new MyStruct();
        NativeAllocateHandle(ref myStruct);
        sh.SetHandle(myStruct.m_outputHandle);
    }

    return sh;
}
1
ответ дан 3 December 2019 в 05:14
поделиться
Другие вопросы по тегам:

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