【问题标题】:Constant running process on a sperate thread blocking a UI thread在阻塞 UI 线程的单独线程上持续运行进程
【发布时间】:2015-12-29 16:12:45
【问题描述】:

我正在尝试使用第三方 telnet 库“活跃专家”进行基本 telnet 会话。 在我后面的 UI 代码中,我有类似

private async void Button_Click(object sender, RoutedEventArgs e)
    {           
        var ts = new TelnetService();
        await ts.DoConnect(node);
    }

我的 TelnetService 看起来像这样

    public class TelnetService
{
    private Tcp objSocket = new Tcp();
    private NwConstants objConstants = new NwConstants();
    public string Responses { get; set; }
    private Timer timer1 = new Timer();

    public TelnetService()
    {
        timer1.Elapsed += timer1_Elapsed;
        timer1.Interval = 100;
        timer1.Start();
    }
    void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (objSocket.ConnectionState == objConstants.nwSOCKET_CONNSTATE_CONNECTED)
        {
            if (objSocket.HasData())
            {
                Responses += objSocket.ReceiveString() + "\r\n";
            }
        }
    }

    public Task DoConnect(Node node)
    {
        return Task.Factory.StartNew(() =>
       {
           objSocket.Protocol = objConstants.nwSOCKET_PROTOCOL_TELNET;
           objSocket.Connect(node.IP, 23);

           while (true)
           {
               if ((Responses == null) || (!Responses.Contains(node.WaitString))) continue;
               //do something
               Responses = "";
               break;
           }
       });
    }

}

有两个重要的功能。

首先在 timer1_Elapsed 函数中,该函数将不断破坏并检查套接字上是否有数据,如果有,它将附加到字符串“Response”。我正在使用“计时器”。

DoConnect 函数中的第二个函数将检查特定输入的“响应”字符串。为此,我正在使用异步等待和任务。

简而言之,第一个累积响应,第二个检查响应。

问题是它看起来像一般的计时器代码

objSocket.ReceiveString()

行特别是导致 UI 线程暂停几秒钟。这意味着单击按钮后,我无法在屏幕上移动主窗体,但是代码在单独的线程中运行。 我曾尝试为此使用纯线程,但它也没有帮助。

更新

我使用的是 AccumulateResponse 方法而不是计时器

public static void AccumulateResponse()
    {
        while (true)
        {
            if (objSocket.ConnectionState == objConstants.nwSOCKET_CONNSTATE_CONNECTED)
            {
                if (objSocket.HasData())
                {
                    Responses += objSocket.ReceiveString() + "\r\n";
                }
            }
        }

    }

并像这样称呼它

   var t = new Task(TelnetService.AccumulateResponse);           
        t.Start();
        await TelnetService.DoConnect(node);

还是没有运气

【问题讨论】:

  • 在创建新任务时在DoConnect() 中调用.ConfigureAwait(continueOnCapturedContext: false);。这将避免使用作为主线程的默认同步上下文。有关详细信息,请参阅此article

标签: c# multithreading async-await task-parallel-library


【解决方案1】:

DoConnect 不是您的问题。它是您的 Timer Elapsed Event 处理程序。

计时器已过事件不是异步的。只有DoConnect 是。

如果您的第三方库中没有ReceiveString() 的异步版本,则在async timer1_elapsed 方法中使用Task.Run

【讨论】:

  • 一定会试试的,会告诉你的
  • 如果在内部使用 Task.Run 不正确,它将在每个 Tick 上运行一个任务。我们想要那个吗?
  • 只要你在等待他们,就不会很糟糕。 Why ...虽然我可能会像他在其他博客条目中所说的那样使用 task.wait,因为他的工作并不是真正受 CPU 限制的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多