是否需要调用?

时间:2014-07-25 11:57:25

标签: c# multithreading winforms sockets exception-handling

设置我的套接字进行连接时,我将方法包装在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)
        {

        }
    }

我只是想确保我以正确的方式这样做

2 个答案:

答案 0 :(得分:1)

在提供的方案中,它使用new ThreadThread.SleepInvoke只是为了在15秒内安排在UI线程上完成一些工作。它会工作,但......效率很低(线程昂贵)。坦率地说,应该使用一个计时器 - 或者可能是Task.Delay在4.5上(实际上它只是包装一个计时器)。

答案 1 :(得分:1)

您最初可以假设连接不会成功,而不是创建连接线程。这将需要轮询计时器重新连接。奖励:您可以控制计时器(虽然您无法对匿名线程执行任何操作),您可以将其用于其他需要轮询的任务(重新发送数据,第一次尝试时未发送,如果更改套接字设置则断开连接后排队连接等)

此轮询计时器可以是普通的UI计时器(如果是winforms,则为Timer),那么您不需要任何调用。如果你这样做,那么请确保没有阻塞操作(例如,发送数据并等待答案)。

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

public static void InvokeIfRequired(this Control control, MethodInvoker action)
{
    if (control.InvokeRequired)
        control.Invoke(action);
    else
        action();
}

在您的情况下,您需要像这样致电Write

someUIControl.InvokeIfRequired(() => Write(...));

或者只需像这样制作Write方法

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