2009-08-30 126 views
6

我有一个类(NamedPipeManager),它有一个线程(PipeThread),它使用(ConnectNamedPipe)等待NamedPipe连接,然后读取(ReadFile) - 这些阻止调用(不重叠) - 然而,点,当我想解除阻止他们 - 例如当呼叫类试图停止NamedPipeManager ...如何取消阻止ConnectNamedPipe和ReadFile? [C#]

我该如何介入它?使用Thread.abort?了Thread.interrupt?有没有适当的方法来处理这个问题? 请参阅下面的代码这说明我目前的状况

main() 
{ 
    NamedPipeManager np = new NamedPipeManager(); 
     ... do stuff ... 
    ... do stuff ... 
    np.Stop();  // at this point I want to stop waiting on a connection 
} 


class NamedPipeManager 
{ 
private Thread PipeThread; 

public NamedPipeManager 
{ 
    PipeThread = new Thread(new ThreadStart(ManagePipes)); 
    PipeThread.IsBackground = true; 
    PipeThread.Name = "NamedPipe Manager"; 
    PipeThread.Start(); 
} 

private void ManagePipes() 
{ 
    handle = CreateNamedPipe(..., PIPE_WAIT, ...); 
    ConnectNamedPipe(handle, null);  // this is the BLOCKING call waiting for client connection 

    ReadFile(....);    // this is the BLOCKING call to readfile after a connection has been established 
    } 


public void Stop() 
{ 
    /// This is where I need to do my magic 
    /// But somehow I need to stop PipeThread 
    PipeThread.abort();  //?? my gut tells me this is bad 
} 
}; 

因此,在功能停止() - 我怎么会优雅地疏通调用ConnectNamedPipe(...)或ReadFile的(...)?

任何帮助,将不胜感激。 谢谢,

回答

4

从Windows Vista开始,有一个可用于线程的CancelSynchronousIO操作。我不认为它有一个C#包装器,所以你需要使用PInvoke来调用它。

在Vista之前,没有一种方法可以优雅地执行这样的操作。我建议不要使用线程取消(这可能有效,但不符合优雅)。你最好的方法是使用重叠的IO。

+0

这是否适用于这两种情况(ConnectNamedPipe&ReadFile)? 我可以找到一种方法,通过伪造一个连接来取消阻止它,然后退出(基于布尔),但我看不到如何解除阻止ReadFile ... 这是通常情况下如何通过ConnectNamedPipe做了什么?处理这种情况必须有一些非同步的方式。 – Shaitan00

+0

顺便说一句 - 这是运行在Windows 2000和XP ...没有Vista的任何时间很快..也使用.Net 2.0 ... 谢谢, – Shaitan00

+0

一种方法是指定一个超时的所有操作,然后本质上执行轮询(例如,对1s执行读操作,然后检查线程是否应该中止,如果不是,则继续读取)。但是,似乎微软真的不相信超时,所以没有API来指定它们。另请参阅http://stackoverflow.com/questions/593175/breaking-readfile-blocking-named-pipe-windows-api –

3

这似乎是工作在VC6.0,WinXP的,如果我试图通过 DeleteFile("\\\\.\\pipe\\yourpipehere");

中断ConnectNamedPipe所以只需指定名称,无法处理。

+0

事实上,DeleteFile在内部按名称打开文件句柄,所以这相当于调用CreateFile()。 –