Domanda

Ho implementato un ciclo motore di gioco come segue:

public static Boolean Start ( )
{
    if (hasBoard)
    {
        //  start engine on worker thread
        asyncTask = new AsyncResult ( stopEngine, asyncTask );
        isRunning = ThreadPool.QueueUserWorkItem ( startEngine, asyncTask );

        if (isRunning)
        {
            Console.WriteLine ( "[{0}] Engine started",
                DateTime.Now.ToString ( "hh:mm:ss" ) );
        }
        else
        {
            Console.WriteLine ( "[{0}] Engine failed to start",
                DateTime.Now.ToString ( "hh:mm:ss" ) );
        }
    }

    return isRunning;
}

public static void Stop ( )
{
    Console.WriteLine ( "[{0}] Engine stopping",
        DateTime.Now.ToString ( "hh:mm:ss" ) );

    asyncTask.SetAsCompleted ( null, false );
}

private static void startEngine ( Object task )
{
    while (!( (IAsyncResult)task ).IsCompleted)
    {
        Thread.Sleep ( 10000 );

        Console.WriteLine ( "[{0}] Engine running",
            DateTime.Now.ToString ( "hh:mm:ss" ) );
    }
}

private static void stopEngine ( IAsyncResult iaResult )
{
    //  clean up resources

    Console.WriteLine ( "[{0}] Engine stopped", 
        DateTime.Now.ToString ( "hh:mm:ss" ) );

    isRunning = false;
}

Sto usando la classe AsyncResult consigliato da Jeff Richter nel suo articolo, Attuazione del CLR asincrono modello di programmazione . Per essere in grado di fermare il motore dall'interfaccia utente, l'applicazione ho usato era un po 'fuori dal modello asincrono standard. Questa implementazione funziona come previsto, ma quando ho devio da una pratica standard, ho tornare alla comunità in modo da garantire che sto facendo le cose nel modo giusto.

Ci sono dei problemi con questa implementazione che chiunque può vedere?

È stato utile?

Soluzione

Dal momento che questo suona come un progetto si ha il controllo, vi suggerisco di fosso APM e utilizzare il modello Task-based fornito in .NET4. Questo è l'approccio raccomandato per .NET4 invece di APM. La classe Task fa parte del Task Parallel biblioteca ( TPL ), ma è grande per questi job asincroni di base pure.

private CancellationTokenSource cts;

public void StartEngine()
{
    if (cts == null)
    {
        cts = new CancellationTokenSource();
        Task.Factory.StartNew(() => GameLoop(cts.Token), cts.Token);
    }
}

private void GameLoop(CancellationToken token)
{
    while (true)
    {
        token.ThrowIfCancellationRequested();
        Thread.Sleep(1000);
        Debug.WriteLine("working...");
    }
}

public void StopEngine()
{
    if (cts != null)
    {
        cts.Cancel();
        cts = null;
    }
}

Altri suggerimenti

direi che è implicito che i compiti sono di breve durata quando si utilizza il pool di thread dal momento che il numero di thread in esso è limitata.

In te caso vorrei usare un BackgroundWorker invece da quando lei ha citato WinForms. BW gestisce la sincronizzazione per voi e sono quindi in grado di aggiornare l'interfaccia grafica senza usare InvokeRequired etc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top