Pergunta

Como definir um tempo limite para um método ocupado + C #.

Foi útil?

Solução

Ok, aqui está a resposta real.

...

void LongRunningMethod(object monitorSync)
{
   //do stuff    
   lock (monitorSync) {
     Monitor.Pulse(monitorSync);
   }
}

void ImpatientMethod() {
  Action<object> longMethod = LongRunningMethod;
  object monitorSync = new object();
  bool timedOut;
  lock (monitorSync) {
    longMethod.BeginInvoke(monitorSync, null, null);
    timedOut = !Monitor.Wait(monitorSync, TimeSpan.FromSeconds(30)); // waiting 30 secs
  }
  if (timedOut) {
    // it timed out.
  }
}

   ...

Isto combina duas das partes mais divertidas de usar C #. Primeiro, para chamar o método de forma assíncrona, use um delegado que tem a magia fantasia-calças BeginInvoke.

Em seguida, use um monitor para enviar uma mensagem da parte de trás LongRunningMethod ao ImpatientMethod para deixá-lo saber quando ele é feito, ou se ele não tenha ouvido falar dele em um determinado período de tempo, apenas dar-se nele.

(p.s.- só brincando sobre este ser a resposta real. Eu sei que existem 2 ^ 9303 maneiras de esfolar um gato. Especialmente em .Net)

Outras dicas

Você não pode fazer isso, a menos que você mudar o método.

Existem duas maneiras:

  1. O método é construído de tal forma a que ela própria mede quanto tempo ele tem sido executado, e em seguida, retorna prematuramente se exceder um limite.
  2. O método é construído de tal forma que ele monitora uma variável / evento que diz "quando esta variável é definida, por favor saída", e então você tem outro segmento medir o tempo gasto no primeiro método, em seguida, definir que variável quando o tempo decorrido ultrapassou um limite.

A mais óbvia, mas infelizmente errada, responda você pode chegar aqui é "Basta executar o método em um fio e uso Thread.Abort quando tem funcionou por muito tempo".

A única maneira correta é para o método de cooperar, de forma que ele vai fazer uma saída limpa quando ele foi executado por muito tempo.

Há também uma terceira via, onde você executa o método em um segmento separado, mas depois de esperar que ela termine, e leva muito tempo para fazer isso, você simplesmente dizer "eu não vou esperar por ele para acabamento , mas apenas descartá-lo". Neste caso, o método ainda será executado, e, eventualmente, terminar, mas que outro segmento que estava esperando por ele vai simplesmente desistir.

Pense na terceira maneira como chamar alguém e pedindo-lhes para procurar a sua casa para que o livro que você emprestou, e depois que você espera no seu lado do telefone por 5 minutos você simplesmente dizer "aw, lançá-lo", e cair acima. Eventualmente, essa outra pessoa vai encontrar o livro e voltar para o telefone, apenas para perceber que você não precisa mais cuidado para o resultado.

Enquanto de MojoFilter resposta é bom ele pode levar a vazamentos se as congela "LongMethod". Você deve abortar a operação, se você não está interessado no resultado mais.

public void LongMethod()
{
    //do stuff
}

public void ImpatientMethod()
{
    Action longMethod = LongMethod; //use Func if you need a return value

    ManualResetEvent mre = new ManualResetEvent(false);

    Thread actionThread = new Thread(new ThreadStart(() =>
    {
        var iar = longMethod.BeginInvoke(null, null);
        longMethod.EndInvoke(iar); //always call endinvoke
        mre.Set();
    }));

    actionThread.Start();
    mre.WaitOne(30000); // waiting 30 secs (or less)
    if (actionThread.IsAlive) actionThread.Abort();
}

Esta é uma questão de idade, mas ele tem uma solução mais simples agora que não estava disponível, então: Tarefas

!

Aqui está um código de exemplo:

var task = Task.Run(() => LongRunningMethod());//you can pass parameters to the method as well
if (task.Wait(TimeSpan.FromSeconds(30)))
    return task.Result; //the method returns elegantly
else
    throw new TimeoutException();//the method timed-out

Você pode executar o método em um segmento separado, e monitorá-lo e forçá-lo a sair se ele funciona muito longo. Uma boa maneira, se você pode chamá-lo como tal, seria desenvolver um atributo para o método em Publicar afiada para que o código assistindo não está desarrumando sua aplicação.

Eu escrevi o seguinte como código de exemplo (observe a parte código de exemplo, ele funciona, mas poderia sofrer problemas de multithreading, ou se o método em questão capta o ThreadAbortException iria quebrá-lo):

static void ActualMethodWrapper(Action method, Action callBackMethod)
{
    try
    {
        method.Invoke();
    } catch (ThreadAbortException)
    {
        Console.WriteLine("Method aborted early");
    } finally
    {
        callBackMethod.Invoke();
    }
}

static void CallTimedOutMethod(Action method, Action callBackMethod, int milliseconds)
{
    new Thread(new ThreadStart(() =>
    {
        Thread actionThread = new Thread(new ThreadStart(() =>
        {
            ActualMethodWrapper(method, callBackMethod);
        }));

        actionThread.Start();
        Thread.Sleep(milliseconds);
        if (actionThread.IsAlive) actionThread.Abort();
    })).Start();
}

Com o seguinte invocação:

CallTimedOutMethod(() =>
{
    Console.WriteLine("In method");
    Thread.Sleep(2000);
    Console.WriteLine("Method done");
}, () =>
{
    Console.WriteLine("In CallBackMethod");
}, 1000);

Eu preciso trabalhar no meu legibilidade do código.

Métodos não têm tempo limite em C #, a menos que seu no depurador ou o OS acredita que a sua aplicação tem 'pendurado'. Mesmo assim, o processamento continua e enquanto você não matar a aplicação de uma resposta é retornada eo aplicativo continua a trabalho.

As chamadas para bancos de dados podem ter limites de tempo.

Você poderia criar um método assíncrono para que você possa continuar a fazer outras coisas enquanto os concluída método "ocupado"?

I aplicativos regularmente gravação onde eu tenho para sincronizar o tempo tarefas críticas através das plataformas. Se você pode evitar Thread.Abort que deveria. Consulte http: // blogs.msdn.com/b/ericlippert/archive/2010/02/22/should-i-specify-a-timeout.aspx e http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation para obter orientações sobre quando Thread.Abort é apropriado. Aqui estão o conceito I implementar:

  • execução seletiva: Só executado se uma chance razoável de sucesso existe (baseado em capacidade de atender tempo limite ou a probabilidade de resultado sucesso em relação a outros itens na fila). Se você quebrar o código em segmentos e saber mais ou menos o tempo de espera entre pedaços de tarefas, você pode prever se você deve ignorar qualquer tratamento posterior. O tempo total pode ser medido pelo envolvendo um tarefas objeto bin com uma função recursiva para o cálculo de tempo ou por ter uma classe de controlador que assiste trabalhadores compete saber os tempos de espera estimado.
  • orfandade seletiva: Apenas esperar que o retorno se chance razoável de sucesso existe. tarefas indexados são executados em uma fila gerenciado. Tarefas que excedem o seu tempo limite ou o risco de causar outros tempos de espera são órfãs e um registro nulo é retornado em seu lugar. Mais tarefas em execução podem ser embrulhados em chamadas assíncronas. Veja o exemplo assíncrona chamada de fardos: http://www.vbusers.com/codecsharp /codeget.asp?ThreadID=67&PostID=1
  • seleção condicional: Semelhante a execução seletiva mas com base em grupo em vez de tarefa individual. Se muitas de suas tarefas estão interligados de tal forma que um sucesso ou falhar torna processamento adicional irrelevante, criar uma bandeira que é verificada antes da execução começa e novamente antes longa em execução sub-tarefas começar. Isto é especialmente útil quando você estiver usando Parallel.For ou outras tarefas, fila de espera de concorrência.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top