中止线程被API调用阻止

时间:2014-12-24 01:57:49

标签: multithreading winapi c#-4.0 timeout thread-abort

我有一个C#WPF程序,它阻止了Windows API调用。当声卡/窗口进入错误状态时,该调用将永久阻止该线程。

我编写了代码,以便程序执行超时'并继续执行该程序。但是,Thread.Abort()调用实际上并未成功中止该线程。一旦用户选择按下关闭,调用API的线程就会继续存在并阻止我的程序稍后关闭。

有没有办法强制关闭挂起的线程?如果没有,是否有更好的方法来关闭应用程序而不是在这种情况下调用Environment.Exit(1)强制应用程序关闭?

代码的简短版本如下所示:

//Program starts
try
{
   new OutputDevice();
}
catch
{ 
    //Tell the user that midi won't work, but otherwise carry on as usual
}

//Output device class
public class OutputDevice():Device
{
    //This method never returns a value when Windows or the hardware misbehave
    [DllImport("winmm.dll")]
    private static extern int midiOutOpen(ref int handle, int deviceID,MidiOutProc proc, int instance, int flags);

    public OutputDevice(int deviceID) : base(deviceID)
    {
        //Set up some variables
        var midiOutProc = HandleMessage;

        //This function calls the windows API when called, and hangs waiting for a response
        Func<int> openMidi = ()=>midiOutOpen(ref hndle, deviceID, midiOutProc, 0, CALLBACK_FUNCTION);

        //Try to call openMidi, and if that times out or returns an error, then throw an exception
        int result;
        if (!TryExecute<int>(openMidi, 20000, out result))
        {
            result = Constants.TimeoutCode;
        }

        if(result != Constants.MMSYSERR_NOERROR)
        {
            throw new Exception(result);
        }
    }

    ///<summary>
    ///Tries to execute a function on another thread. If the operation times out, aborts the thread and returns false.
    ///</summary>
    public static bool TryExecute<T>(Func<T> func, int timeout_milliseconds, out T result)
    {
        var t = default(T);
        var thread = new System.Threading.Thread(() => t = func());
        thread.Start();
        var completed = thread.Join(timeout_milliseconds);
        if (!completed)
        {
            //timeout
            thread.Abort();
        }
        result = t;
        return completed;
    }

    ///<summary>
    /// Handles Windows messages.
    /// </summary>
    protected virtual void HandleMessage(int handle, int msg, int instance, int param1, int param2)
    {
    //Handle the message
    }
}

谢谢!

0 个答案:

没有答案