【问题标题】:How do you update ASP.NET web forms from different threads?如何从不同的线程更新 ASP.NET Web 表单?
【发布时间】:2013-07-27 00:40:26
【问题描述】:

在过去的几天里,我一直在努力学习如何将 ASP.NET Web 窗体与多线程一起使用,方法是使用两者构建一个简单的小程序,并且我一直在努力解决不同线程之间交互的各个方面和用户界面。

我已经在其他一些问题中解决了一些多线程问题(并且在 waaaaaay 之后也了解到 Web 表单和 WPF 不是一回事)但现在我在寻找基于更新 UI 元素的最佳方法时遇到了麻烦在多个线程中获取的数据。

这是我的代码:

Default.aspx

public partial class _Default : System.Web.UI.Page
{
    private NlSearch _search;
    private static int _counter = 0;
    private static SortedList<long, SearchResult> resultsList = new SortedList<long, SearchResult>();

    protected void Page_Load(object sender, EventArgs e)
    {
        _search = new NlSearch();
    }

    protected void AddSearchMethod(object sender, EventArgs e)
    {
        var text = SearchForm.Text;
        new Task(() => MakeRequest(text));
    }

    protected void UpdateMethod(object sender, EventArgs e)
    {
        resultsLabel.Text = "";
        foreach (var v in resultsList.Values)
        {
            resultsLabel.Text += v.SearchTerm + ": " + v.Count + " occurances<br/>";
        }
    }

    protected void ClearSearchMethod(object sender, EventArgs e)
    {
        resultsLabel.Text = "";
        resultsList.Clear();
    }

    protected void MakeRequest(string text)
    {
        _counter++;
        SearchResult s = new SearchResult
        {
            SearchTerm = text,
            Count = _search.MakeRequests(text)
        };
        resultsList.Add(_counter, s);
    }
}

我已经尝试了很多相同的基本版本。 NlSearch.MakeRequest(由 MakeRequests 调用)将 HTTP POST 请求发送到模仿搜索栏输入的外部网站,然后从标记中提取一个整数,指示返回了多少结果。

当前的简单 UI 围绕着一个 SearchForm 文本字段、一个“添加搜索”按钮、一个“更新标签”按钮、一个“清除搜索”方法和一个显示结果的 ResultsLabel。 AddSearch 按钮创建一个调用 MakeRequest 的新任务,该任务调用该方法来发送 HTTP 请求,然后将结果按发送顺序存储在静态排序列表中。

所以现在理想情况下,在一个好的 UI 中,我只想在每次线程返回时更新标签,但是我尝试使用 ContinueWhenAll 和其他一些任务函数,问题似乎是其他线程没有更改 UI 的能力。

我还尝试在页面加载时运行一个新线程,每隔几秒更新一次标签,但这同样失败了。

因为我无法正确实现这一点,我不得不使用“更新标签”按钮,它实际上只是告诉标签显示静态列表中的当前内容。我真的很想摆脱这个按钮,但我不知道如何让我的线程进行 UI 更改。

【问题讨论】:

    标签: c# asp.net multithreading webforms


    【解决方案1】:

    一般来说,尝试在 Web 应用程序中执行线程是一个坏主意。 Web 服务器就是为此而设计的,但应尽可能避免分离新线程或进程。虽然曾经有一种机制(也许现在仍然存在)将结果“推送”给客户,但现在有更好的解决方案可用。

    您所描述的正是 AJAX 旨在解决的问题。

    【讨论】:

      【解决方案2】:

      您在问题中提到了 WPF——您是否可能正在寻找 Windows 应用程序,例如 WinForms?我认为也许“网络表单”这个词混淆了这种情况。 Web 表单只是添加了一些(好吧,很多)Microsoft 功能的网页。

      听起来您正试图从代码中的线程向网页发送更新。网络不是这样工作的。如果您实际上正在尝试设计网页,我建议您阅读ASP.NET Page Life Cycle Overview。其他答案建议使用 AJAX 功能(这是网页执行一些 JavaScript 并与 Web 服务器对话的地方)。

      【讨论】:

      • 那么在这个应用程序中是否没有简单的方法来定期更新/更新标签而无需用户明确按下按钮?我只是不明白为什么不使用 AJAX 就无法在 C# 后端进行操作。为什么主线程可以更新UI元素,而其他线程却没有办法这样做,鉴于此,在c#中真的没有简单的方法来添加一个简单的更新例程吗?
      • 或者,换句话说,如果存在的话,我宁愿使用一个简单的解决方法,而不是现在钻研学习 AJAX。
      • 虽然这看起来很简单,但网络的底层结构却无法做到这一点。主线程以特定(尽管很复杂)的顺序更新 UI 元素,然后停止执行。 Unload 事件(在上面的生命周期概述中提供)停止与页面本身的通信。网页并不意味着像 Windows 窗体那样处理,您可以通过向侦听器广播更新消息来更新客户端。客户必须通过网络上的服务器进行登记。这就是 HTTP 的本质。
      • 继续:这就是 AJAX 存在的具体原因。您将在 ASP.NET 中看到的 hack(例如 UpdatePanelsAutoPostBack 控件)都使用 JavaScript 和 AJAX 在幕后与服务器通信。交互式网站使用 JavaScript、jQuery 或其他 JavaScript 库来抽象出创建 AJAX 请求的潜在困难。
      • @ProtonBetaDecay:由于 HTTP 的工作方式,您想要做的事情是不可能的:您打开连接,发出请求,接收结果,然后关闭连接。此时,客户端和服务器之间不再有交互。 HTTP 的工作方式没有简单的解决方法,如果您确实发现了一些黑客攻击,它可能会被视为安全问题并很快修补。
      【解决方案3】:

      您以前听说过 AJAX 吗?我认为您是应用程序开发人员而不是 Web 开发人员的思考方式。

      【讨论】:

      • 听说过但没用过。应用程序开发而不是 Web 开发是什么意思?
      • 是的,Web 是无状态的,通常您使用 Session 来维护 Web 应用程序的状态。在您的特定情况下,AJAX 帮助您在 Web 应用程序中开发异步行为(您可以执行多个请求,获取结果并在页面中显示这些结果)。基于异步事件的编程主要专注于开发桌面应用程序或填补移动应用程序的空白。
      • 我找到了一种在服务器端进行异步处理的方法。它使用 ASP .Net MVC 4。msdn.microsoft.com/en-us/library/ee728598(v=vs.100).aspx
      【解决方案4】:

      如果您想异步运行代码,您可能需要使用 Async Await 关键字,而不是自己管理线程。 See information about Asynchronous Programming with Async and Await

      不要让你的线程纠结;)

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-22
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 2010-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多