ما هو وسيلة جيدة اغلاق المواضيع المحظورة على NamedPipeServer#WaitForConnection?

StackOverflow https://stackoverflow.com/questions/607872

  •  03-07-2019
  •  | 
  •  

سؤال

بدء التطبيق الذي يولد عدد من المواضيع كل منهما يخلق NamedPipeServer (.net framework 3.5 وأضاف تدار من أنواع المسمى IPC) و ينتظر العملاء للاتصال (كتل).مدونة وظائف على النحو المنشود.

private void StartNamedPipeServer()
  {
    using (NamedPipeServerStream pipeStream =
                    new NamedPipeServerStream(m_sPipeName, PipeDirection.InOut, m_iMaxInstancesToCreate, PipeTransmissionMode.Message, PipeOptions.None))
    {
      m_pipeServers.Add(pipeStream);
      while (!m_bShutdownRequested)
      {
        pipeStream.WaitForConnection();
        Console.WriteLine("Client connection received by {0}", Thread.CurrentThread.Name);
        ....  

الآن أنا أيضا في حاجة إلى إيقاف طريقة لجلب هذه العملية إلى أسفل نظيفة.حاولت المعتاد منطقي العلم isShutdownRequested خدعة.ولكن pipestream يبقى حظر على WaitForConnection() الدعوة موضوع لا يموت.

public void Stop()
{
   m_bShutdownRequested = true;
   for (int i = 0; i < m_iMaxInstancesToCreate; i++)
   {
     Thread t = m_serverThreads[i];
     NamedPipeServerStream pipeStream = m_pipeServers[i];
     if (pipeStream != null)
     {
       if (pipeStream.IsConnected)
          pipeStream.Disconnect();
       pipeStream.Close();
       pipeStream.Dispose();
     }

     Console.Write("Shutting down {0} ...", t.Name);
     t.Join();
     Console.WriteLine(" done!");
   }
} 

الانضمام لا يعود أبدا.

وهو الخيار الذي لم تحاول ولكن من المحتمل ان العمل هو الدعوة الى الموضوع.إحباط وتلتهم استثناء.لكنه لا يشعر الحق..أي اقتراحات

تحديث 2009-12-22
آسف لعدم نشر في وقت سابق من هذا..هذا ما كنت تلقى استجابة من كيم هاميلتون (BCL فريق)

"الحق" وسيلة للقيام وعدم انقطاع WaitForConnection هو الاتصال BeginWaitForConnection ، والتعامل مع الجديد اتصال في الاستدعاء ، وإغلاق الأنابيب تيار لوقف انتظار اتصالات.إذا كان أنبوب مغلق ، EndWaitForConnection سوف رمي ObjectDisposedException التي رد خيط الصيد ، تنظيف أي المغفلة ، والخروج نظيفة.

ونحن ندرك أن هذا يجب أن يكون مشترك السؤال: إذا شخص على فريقي تخطيط بلوق عن هذا قريبا.

هل كانت مفيدة؟

المحلول

التبديل إلى غير متزامن الإصدار: BeginWaitForConnection.

إذا لم كاملة من أي وقت مضى, سوف تحتاج إلى العلم حتى الانتهاء معالج يمكن أن مجرد دعوة EndWaitForConnection استيعاب أي استثناءات والخروج (إنهاء المكالمة...لضمان أي موارد قادرة على تنظيف).

نصائح أخرى

هذا هو جبني, ولكن هذا هو الأسلوب الوحيد لقد حصلت على العمل.إنشاء 'وهمية' العميل الاتصال المسمى على تجاوز WaitForConnection.يعمل في كل مرة.

أيضا, حتى موضوع.إحباط() لا إصلاح هذه المشكلة بالنسبة لي.


_pipeserver.Dispose();
_pipeserver = null;

using (NamedPipeClientStream npcs = new NamedPipeClientStream("pipename")) 
{
    npcs.Connect(100);
}

يمكنك استخدام طريقة تمديد التالية.ملاحظة إدراج 'ManualResetEvent cancelEvent' - يمكنك تعيين هذا الحدث من مؤشر ترابط آخر في إشارة إلى أن انتظار ربط الأسلوب يجب إجهاض الآن إغلاق الأنابيب.وتشمل cancelEvent.مجموعة() عند وضع m_bShutdownRequested و اغلاق يجب أن يكون نسبيا رشيقة.

    public static void WaitForConnectionEx(this NamedPipeServerStream stream, ManualResetEvent cancelEvent)
    {
        Exception e = null;
        AutoResetEvent connectEvent = new AutoResetEvent(false);
        stream.BeginWaitForConnection(ar =>
        {
            try
            {
                stream.EndWaitForConnection(ar);
            }
            catch (Exception er)
            {
                e = er;
            }
            connectEvent.Set();
        }, null);
        if (WaitHandle.WaitAny(new WaitHandle[] { connectEvent, cancelEvent }) == 1)
            stream.Close();
        if (e != null)
            throw e; // rethrow exception
    }

كتبت هذا التمديد طريقة لحل هذه المشكلة:

public static void WaitForConnectionEx(this NamedPipeServerStream stream)
{
    var evt = new AutoResetEvent(false);
    Exception e = null;
    stream.BeginWaitForConnection(ar => 
    {
        try
        {
            stream.EndWaitForConnection(ar);
        }
        catch (Exception er)
        {
            e = er;
        }
        evt.Set();
    }, null);
    evt.WaitOne();
    if (e != null)
        throw e; // rethrow exception
}

إحدى الطرق التي يمكن أن تعمل على فحص m_bShutdownRequested بعد WaitForConnection.

أثناء عملية إيقاف التشغيل وضع منطقي.بعد ذلك إرسال الرسائل الوهمية إلى جميع الأنابيب القائمة حتى فتح الاتصال والتحقق منطقي و اغلاق نظيفة.

وهو أبسط وسهلة الحل هو إنشاء دمية العميل والقيام اتصال مع الملقم.

NamedPipeServerStream pServer;
bool exit_flg=false;
    public void PipeServerWaiter()
{

    NamedPipeServerStream  pipeServer = new NamedPipeServerStream("DphPipe", PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances);
    pServer = pipeServer;
    pipeServer.WaitForConnection();


    if (exit_flg) return;
    thread = new Thread(PipeServerWaiter);
    thread.Start();

}
public void Dispose()
{
    try
    {
        exit_flg = true;
        NamedPipeClientStream clt = new NamedPipeClientStream(".", "DphPipe");
        clt.Connect();
        clt.Close();

        pServer.Close();
        pServer.Dispose();


    }
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Pipes;
using System.Threading;
using System.Windows;
using System.Windows.Controls;

namespace PIPESERVER
{
    public partial class PWIN : UserControl
   {
    public string msg = "", cmd = "", text = "";
    public NamedPipeServerStream pipe;
    public NamedPipeClientStream dummyclient;
    public string PipeName = "PIPE1";
    public static string status = "";
    private static int numThreads = 2;
    int threadId;
    int i;
    string[] word;
    char[] buffer;
    public StreamString ss;

    public bool ConnectDummyClient()
    {
        new Thread(() =>
        {
            dummyclient = new NamedPipeClientStream(".", "PIPE1");
            try
            {
                dummyclient.Connect(5000); // 5 second timeout
            }
            catch (Exception e)
            {
                Act.m.md.AMsg(e.Message); // Display error msg
                Act.m.console.PipeButton.IsChecked = false;
            }
        }).Start();
        return true;
    }

    public bool RaisePipe()
    {
        TextBlock tb = Act.m.tb;
        try
        {
            pipe = new NamedPipeServerStream("PIPE1", PipeDirection.InOut, numThreads);
            threadId = Thread.CurrentThread.ManagedThreadId;
            pipe.WaitForConnection();
            Act.m.md.Msg("Pipe Raised");
            return true;
        }
        catch (Exception e)
        {
            string err = e.Message;
            tb.Inlines.Add(new Run("Pipe Failed to Init on Server Side"));
            tb.Inlines.Add(new LineBreak());
            return false;
        }
    }

    public void ServerWaitForMessages()
    {
        new Thread(() =>
        {
            cmd = "";
            ss = new StreamString(pipe);
            while (cmd != "CLOSE")
            {
                try
                {
                    buffer = new char[256];
                    text = "";
                    msg = ss.ReadString().ToUpper();
                    word = msg.Split(' ');
                    cmd = word[0].ToUpper();
                    for (i = 1; i < word.Length; i++) text += word[i] + " ";
                    switch (cmd)
                    {
                        case "AUTHENTICATE": ss.WriteString("I am PIPE1 server"); break;
                        case "SOMEPIPEREQUEST":ss.WriteString(doSomePipeRequestReturningString()):break;
                        case "CLOSE": ss.WriteString("CLOSE");// reply to client
                            Thread.Sleep(1000);// wait for client to pick-up shutdown message
                            pipe.Close();
                            Act.m.md.Msg("Server Shutdown ok"); // Server side message
                            break;
                    }
                }
                catch (IOException iox)
                {
                    string error = iox.Message;
                    Act.m.md.Msg(error);
                    break;
                }
            }
        }).Start();
    }

    public void DummyClientCloseServerRequest()
    {
        StreamString ss = new StreamString(dummyclient);
        ss.WriteString("CLOSE");
        ss.ReadString();
    }

//الاستخدام ، مكان ToggleButtons داخل StackPanel ، ويعود لهم في التعليمات البرمجية كما يلي:

private void PipeButton_Checked(object sender, RoutedEventArgs e)
    {
        Act.m.pwin.ConnectDummyClient();
        Act.m.pwin.RaisePipe();
    }
private void PipeButton_Unchecked(object sender, RoutedEventArgs e)
    {
        Act.m.pwin.DummyClientCloseServerRequest();
        Act.m.console.WaitButton.IsChecked = false;
        Keyboard.Focus(Act.m.md.tb1);
    }
private void WaitButton_Checked(object sender, RoutedEventArgs e)
    {
        Act.m.pwin.Wait();
    }
private void WaitButton_Unchecked(object sender, RoutedEventArgs e)
    {
    }

//يعمل مثل السحر بالنسبة لي.بكل احترام ، zzzbc }

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top