2016-06-01 8 views
3

Есть ли способ в C# вызвать метод, чтобы, если метод длится до завершения, метод будет отменен, и он вернется к вызывающему методу? Я думаю, что могу сделать это с помощью потоковой передачи, но что делать, если потоки не нужны?Вызвать метод и отменить его и вернуться к вызывающему методу, если он слишком длинный

Для справки, метод, который мне может потребоваться для уничтожения/остановки/прерывания, вызывает API CorelDraw 15. Это открывает экземпляр CorelDraw, и я получил неповторяющиеся ошибки в этом методе. Смысл, я могу обработать одно и то же изображение дважды, и один раз он замерзнет или будет ошибкой, а другой - нет.

Текущее решение проблемы, которую я использую, состоит в том, чтобы иметь второе приложение, которое делает Process.Start(firstAppExecutablePath), а затем проверяет переменную в текстовом файле и, если переменная не изменяется через 10 минут, вызывается .Kill(); в экземпляре процесс. Я бы предпочел избежать этого решения, если это возможно, поскольку оно кажется неуклюжим и подверженным проблемам. Поскольку он работает .Kill();, он очень запутан в том, как все близко, но, как правило, не вызывает проблемы.

+4

Если это не резьбовые, то нет никакого способа проверить тайм-аут, потому что выполняющийся поток выполняет свой метод. Нет ничего, что можно было бы проверить: «Это слишком долго?» – dman2306

+4

Является ли ваш api асинхронным? Для этого и служит CancellationToken. – Crowcoder

+1

Что такое метод? – Luaan

ответ

0

Threading абсолютно необходим, если вы не в состоянии проверить тайм-аут из функции, которая, вероятно, вы не используете. Так вот минималистичный подход нитками:

private static bool ExecuteWithTimeout(TimeSpan timeout, Action action) 
{ 
    Thread x = new Thread(() => { action(); }); 
    x.Start(); 

    if (!x.Join(timeout)) 
    { 
     x.Abort(); //Or Interrupt instead, if you use e.g. Thread.Sleep in your method 
     return false; 
    } 

    return true; 
} 
+3

Не рекомендуется прерывать другие темы.Если в другом потоке выполняется статический конструктор, вы рискуете никогда не иметь возможности построить объект этого типа с этим конструктором в этом процессе. См. Примечание в [документации] (https://msdn.microsoft.com/en-us/library/ty8d3wta (v = vs.110) .aspx # Anchor_2). –

+0

@Cameron 'x.Abort()' не «отменяет» его, и поток «счастливо продолжает делать свое дело»? Я считаю, что трудно поверить ... –

+0

@ LasseV.Karlsen Да, это было бы плохо. Вот почему (если бы мы знали, какие родственники кода OP пытаются отменить), то предпочтительнее всего использовать CancellationToken или, по крайней мере, и прерывание вместо Abort. –

1

Не встроенный, нет, так как прерывание произвольного кода не может быть сделано безопасно (что, если это в середине вызова библиотечной функции C (которая не поддерживает исключения), который только что сделал глобальную блокировку и должен ее выпустить?).

Но вы можете написать такую ​​поддержку самостоятельно. Я бы не добавлял нити в смесь, если это абсолютно необходимо, поскольку они имеют совершенно новое измерение потенциальных проблем.

Пример:

void Caller() 
{ 
    int result; 
    if (TryDoSomething(out result, 100)) { 
     System.Console.WriteLine("Result: {0}", result); 
    } 
} 

bool TryDoSomething(out int result, int timeoutMillis) 
{ 
    var sw = Stopwatch.StartNew(); 
    result = 0x12345678; 
    for (int i = 0; i != 100000000; ++i) { 
     if (sw.ElapsedMilliseconds > timeoutMillis) 
      return false; 
     result += i/(result % 43) + (i % 19); 
    } 
    return true; 
} 
+0

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

+0

@ Крис согласился. Вы предполагаете, что метод можно изменить, чтобы проверить, как долго он работает. Что делать, если я пытаюсь отключить операцию ввода-вывода, которая просто блокируется? – dman2306

+0

'TryDoSomething' * - это один метод ;-) Большинство методов могут быть проверены на тайм-аут на стратегических позициях. Цикл был всего лишь примером. И да, это предполагает контроль над целевым методом, который с тех пор показал, что это не относится к ОП. Я оставлю ответ в общем случае. Операции ввода-вывода и других операций на уровне ОС имеют неблокирующие версии, которые могут быть интегрированы с таймаутами с достаточным усилием. – Cameron