Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 是否需要调用?_C#_Multithreading_Winforms_Sockets_Exception Handling - Fatal编程技术网

C# 是否需要调用?

C# 是否需要调用?,c#,multithreading,winforms,sockets,exception-handling,C#,Multithreading,Winforms,Sockets,Exception Handling,在设置连接套接字时,我将该方法包装在try-catch块中 如果引发套接字异常,我将创建一个新线程。。睡15秒钟。。然后再次调用connect方法,但这次是从另一个线程调用。我这样做主要是为了睡眠方法(避免使用计时器重新连接)不挂断主线程 无论如何。。在尝试连接时,我使用一个名为write()的方法将状态写入文本框,该方法只会在当前文本前添加一个\n 因为在一个失败的连接上,我创建了一个单独的线程来调用connect方法(它会修改表单上的控件),所以我可以在方法调用上使用invoke,对吗 这是

在设置连接套接字时,我将该方法包装在try-catch块中

如果引发套接字异常,我将创建一个新线程。。睡15秒钟。。然后再次调用connect方法,但这次是从另一个线程调用。我这样做主要是为了睡眠方法(避免使用计时器重新连接)不挂断主线程

无论如何。。在尝试连接时,我使用一个名为write()的方法将状态写入文本框,该方法只会在当前文本前添加一个\n

因为在一个失败的连接上,我创建了一个单独的线程来调用connect方法(它会修改表单上的控件),所以我可以在方法调用上使用invoke,对吗

这是我的密码

private void Connect()
    {
        try
        {
            Write("Connecting...");
            _ClientSocket.Connect(new IPEndPoint(IPAddress.Loopback, 2500));
            Connected = true;
            Write("Connected.");
            _ClientSocket.BeginReceive(Buffer, 0, Buffer.Length, 0, new AsyncCallback(RecieveCallBack), null);
        }
        catch (SocketException ex)
        {
            Write("Connection Failed. Trying again in 15 Seconds...");
            Connected = false;
            new Thread(delegate()
            {
                Thread.Sleep(15000);
                Invoke((MethodInvoker)delegate
                {
                    this.Connect();
                });
            }).Start();
        }
        catch (Exception ex)
        {

        }
    }

我只是想确定我是以正确的方式来做这件事的

在所展示的场景中,它使用了
新线程
线程。睡眠
调用
仅仅是一种在15秒内安排UI线程上发生一些工作的方式。会有用的,但是。。。效率很低(线程很昂贵)。坦白地说,应该改用定时器——或者可能是4.5上的任务延迟(实际上只是包装了一个定时器)。

不要创建线程来连接,你可以先假设,你的连接不会成功。这需要有轮询计时器才能重新连接。奖金:您可以控制计时器(而您不能对匿名线程执行任何操作),您可以将其用于其他需要轮询的任务(重新发送第一次尝试时未传递的数据,如果您更改套接字设置,请在断开连接后排队连接等)

这个轮询计时器可以是一个普通的UI计时器(在winforms的情况下),那么您就不需要任何调用。如果您这样做,那么请确保其中没有阻塞操作(例如,发送数据并等待回答)

否则,您可以对方法使用扩展方法来始终在UI线程中运行它们

public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
    if (control.InvokeRequired)
        control.Invoke(action);
    else
        action();
}
在您的情况下,您将希望像这样调用
Write

someUIControl.InvokeIfRequired(() => Write(...));
void Write(...)
{
    if(someUIControl.InvokeRequired)
        someUIControl.Invoke((delegate)() => Write(...));
    else
    {
        ... job here
    }
}
或者简单地让
Write
方法如下

someUIControl.InvokeIfRequired(() => Write(...));
void Write(...)
{
    if(someUIControl.InvokeRequired)
        someUIControl.Invoke((delegate)() => Write(...));
    else
    {
        ... job here
    }
}

测试应该回答你的问题。它在没有调用的情况下工作吗?它与调用一起工作吗?如果答案分别是“否”和“是”,那么看起来你做了正确的事情。如果答案是“是”和“是”,那么您不需要调用。您的UI框架是什么?我很确定这种做法是错误的,尤其是在C#5.0世界,我看不出你在哪里访问WinForms。也不要手动创建线程。例如,使用ThreadPool.QueueUserWorkItem这不是一个好主意。除了忘记使用BeginInvoke()之外,如果在Connect()调用之后连接了套接字,那么您还可以创建额外的bug。因此,将项目符号字节化,并始终启动一个线程。现在一切都很明显了,包括问题的答案。@HansPassant所以你建议跳过主线程中的连接,总是在单独的线程中连接?除了调用答案之外,我非常感谢关于轮询计时器的建议。我明白这是多么有用。