Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.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# 在单独的线程中执行操作以取消阻止UI_C#_Asp.net Mvc_Asp.net Mvc 4 - Fatal编程技术网

C# 在单独的线程中执行操作以取消阻止UI

C# 在单独的线程中执行操作以取消阻止UI,c#,asp.net-mvc,asp.net-mvc-4,C#,Asp.net Mvc,Asp.net Mvc 4,我有一个用来生成报告的表单。我们使用的是RDLC报告,报告加载到aspx页面中 这是表单的代码,表单目标设置为\u blank,并在新选项卡中打开 @using (Html.BeginForm("AssetReports", "AssetReports", FormMethod.Post, new { target = "_blank" })) { <div class="row mt-15"> <div class="col-md-12 text-ce

我有一个用来生成报告的表单。我们使用的是
RDLC
报告,报告加载到
aspx
页面中

这是
表单
的代码,表单目标设置为
\u blank
,并在新选项卡中打开

@using (Html.BeginForm("AssetReports", "AssetReports", FormMethod.Post, new { target = "_blank" }))
{
    <div class="row mt-15">
        <div class="col-md-12 text-center">
            <input type="submit" class="btn btn-primary" value="Show Report" />
        </div>
    </div>
}
在某些情况下,生成报告需要3,4分钟。在这段时间里,用户界面被阻塞

我们希望在单独的线程上生成报告,以便用户可以在生成报告时使用UI

MVC中有没有一种方法可以在单独的线程中执行此操作

我尝试过使用以下内容,但上下文和会话随后为
NULL

Task.Factory.StartNew(() =>
{
    switch (model.SelectedReportType)
    {
        case AssetReportTypesEnum.ExcessiveIdleReport:
            Response.Redirect("~/Reports/AssetReports/ExcessiveIdleReport/ExcessiveIdleReport.aspx");
            break;
    }
});
而且:

new Thread(() =>
{
    switch (model.SelectedReportType)
    {
        case AssetReportTypesEnum.ExcessiveIdleReport:
            Response.Redirect("~/Reports/AssetReports/ExcessiveIdleReport/ExcessiveIdleReport.aspx");
            break;
    }
}).Start();
编辑

生成报告的代码-这是需要3到4分钟的代码ExcessiveIdleReport.aspx

public partial class ExcessiveIdleReport1 : Page
    {
        private IReportsProvider _reportsProvider;

        protected void Page_Load(object sender, EventArgs e)
        {
            _reportsProvider = new ReportsProvider();
            if (!IsPostBack)
            {
                try
                {
                    var reportDetails = SessionHandler.AssetReport;
                    var reportParams = SessionHandler.AssetReportParameters;



                    var sPath = Server.MapPath("../ExcessiveIdleReport/ExcessiveIdleReport.rdlc");
                    var dsExcessiveReport =
                        _reportsProvider.GetExcessiveIdleReport(reportDetails.CompanyId, reportDetails.AssetId, reportDetails.StartDate,
                                                                reportDetails.EndDate, reportParams.SelectedIdleTime * 60);

                    ExcessiveIdleReportViewer.ProcessingMode = ProcessingMode.Local;
                    ExcessiveIdleReportViewer.LocalReport.EnableHyperlinks = true;
                    ExcessiveIdleReportViewer.HyperlinkTarget = "_blank";
                    ExcessiveIdleReportViewer.LocalReport.DataSources.Add(new ReportDataSource("ExcessiveIdleReport", dsExcessiveReport.Tables[0]));
                    ExcessiveIdleReportViewer.LocalReport.DataSources.Add(new ReportDataSource("ReportHeaderDetails", dsExcessiveReport.Tables[1]));
                    ExcessiveIdleReportViewer.LocalReport.DataSources.Add(new ReportDataSource("ReportSummary", dsExcessiveReport.Tables[2]));
                    ExcessiveIdleReportViewer.LocalReport.ReportPath = sPath;

                    ExcessiveIdleReportViewer.LocalReport.EnableExternalImages = true;
                    ExcessiveIdleReportViewer.LocalReport.SetParameters(param);

                    ExcessiveIdleReportViewer.LocalReport.Refresh();

                }
                catch (Exception ex)
                {
                    ErrorDiv.InnerText = string.Format("An error occured while generating the ExcessiveIdleReport, Please contact Support with following Message: [{0}] - [{1}]", ex.Message, ex.StackTrace);
                    ReportContentDiv.Visible = false;
                    ErrorDiv.Visible = true;
                }
            }
        }
    }
我也尝试过使用Ajax.BeginForm

 @using (Ajax.BeginForm("AssetReports", "AssetReports", new AjaxOptions() { HttpMethod = "POST", OnSuccess = "OpenReport"}, new { target = "_blank" }))
            {

            <div class="row mt-15">
                <div class="col-md-12 text-center">
                    <input type="submit" class="btn btn-primary" value="Show Report" />
                </div>
            </div>
}
我使用Ajax加载所有其他页面:

以下是执行操作的资产报告页面“显示报告”按钮的图像:

但一旦单击此按钮,其他UI元素将被阻止。e、 g.在生成报告之前,我无法使用
组报告加载视图


在逻辑中添加线程不是运行不“锁定”UI的东西的方法。对ASP.NET MVC应用程序的每个新请求都会自动在一个新线程上提供。如果不是这样,那么多人将无法同时访问您的站点

答案的关键是AJAX。AJAX请求是在后台启动请求的东西

探索将
@using(Html.BeginForm)(
替换为
@using(Ajax.BeginForm)(
)以在不重新加载页面的情况下发出请求。例如,您还可以使用
$jQuery.Ajax()
通过单击按钮启动请求

jQuery.Ajax()
ASP.NET MVC倾向于序列化同一会话的请求,除非指定该会话为只读

在Microsoft的这篇文章中,它指出:

并发请求和会话状态

每个会话对ASP.NET会话状态的访问是独占的,这意味着 如果两个不同的用户同时发出请求,则访问每个用户 同时授予单独的会话。但是,如果两个会话同时 对同一会话发出请求(使用同一会话ID 值),第一个请求以独占方式访问会话 第二个请求仅在第一个请求之后执行 已完成。(如果是独占会话,则第二个会话也可以获得访问权限。) 由于第一个请求超过了 锁定超时。)如果@Page中的EnableSessionState值 指令设置为只读,这是对只读会话的请求 信息不会导致对会话数据的独占锁定。 但是,会话数据的只读请求可能仍需要等待 对于由要清除的会话数据的读写请求设置的锁

您可能希望将会话状态设置为只读,或者使用更合理的技术,如node.js(最后一点只是开个玩笑…)

John Culviner的文章如下所示:

mvc3的一种解决方案

幸运的是,Microsoft在中提供了枚举值 允许我们放弃的System.Web.SessionState.SessionState行为 独占会话锁的权限。主要值:

只读–不阻止其他请求,因为此请求无法 更新会话已禁用–无法阻止,是您的最佳选择 在StateServer和SQL模式下的性能,因为不需要序列化 记住,所有会话都是序列化和反序列化的 每次每个用户。不仅仅是您正在访问的特定密钥

在服务器上抛出一个带有所需枚举值的新for MVC 3属性 控制器类本身:


最后,使用@goofballLogic的答案,我找到了答案

当我使用
.aspx
页面在新选项卡中生成报告时,我必须在aspx页面中将会话状态设置为
readonly
,而不是控制器

您可以通过将属性
EnableSessionState=“ReadOnly”
添加到
页面
标记中来完成此操作

<%@ Page Language="C#" EnableSessionState="ReadOnly" AutoEventWireup="true" CodeBehind="ExcessiveIdleReport.aspx.cs"" %>

看看如何使用Ajax.BeginForm,这样您就可以使客户端的调用异步。@JustinHarvey是否可以在新选项卡中打开Ajax表单?使用Form.BeginForm除了呈现标准HTML(如:)之外没有任何特殊功能,因此不应该涉及任何阻塞。您确定页面上没有javascript例程吗在提交表单后,哪一个阻止了交互?@goofballLogic否,它只是一个简单的提交(target=“\u blank”),然后重定向到aspx页面。@重定向后的goofballLogic主页被阻止,直到生成报告。您是说Ajax.BeginForm吗?是否可以在新选项卡中打开Ajax表单?我不想在同一选项卡/窗口中显示报告您可以通过向表单..我将添加一个示例在生成报告之前这仍然会阻塞UI编辑可能是因为您需要安装相关的Nuget软件包(如果您还没有),以支持Ajax.BeginForm或只是,直到那时它将像普通表单一样运行。谢谢。我将对此进行研究,并了解其进展情况。我很高兴您能够成功访问最后!我不知道会话状态/只读,所以它教会了我一些新的东西。谢谢!也适用于crystal reports。谢谢。
function OpenReport(response) {
    var popup = window.open("about:blank", "_blank"); // the about:blank is to please Chrome, and _blank to please Firefox
    popup.location = '/TBReports/AssetReports/ExcessiveIdleReport/ExcessiveIdleReport.aspx';
}
$(document).delegate('#myForm', 'submit', function(e) {

    e.preventDefault();

    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: '/AssetReports',
        data: $('#myForm').serialize(), // Post data from form
        success: function (responseData) {

             // Perform redirect to report?
        },
        error: function (jqXHR, textStatus, errorThrown) {

             // Display error?
        }
    })
});

@using (Html.BeginForm("AssetReports", "AssetReports", FormMethod.Post, new { target = "_blank", id = "myForm" })) // Added id
{
    <div class="row mt-15">
        <div class="col-md-12 text-center">
            <input type="submit" class="btn btn-primary" value="Show Report" />
        </div>
    </div>
}
 function OpenReport(data, status, xhr) {

     // Open the report in a new window
     window.open("\\link\to\report");
 }

 @using (Ajax.BeginForm("AssetReports", "AssetReports", null, new AjaxOptions { HttpMethod = "POST", OnSuccess = "OpenReport" }, new { target = "_blank" }))
 {
     // ... Form
 }
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class TestController : Controller
{
    public ActionResult Index()
    {
        System.Threading.Thread.Sleep(10000);
        return new EmptyResult();
    }
}
<%@ Page Language="C#" EnableSessionState="ReadOnly" AutoEventWireup="true" CodeBehind="ExcessiveIdleReport.aspx.cs"" %>