无法与 C# Winform 中的日志记录任务并行获取 运行 的存储过程

Cant get Stored Procedure to run in parallel to logging task in C# Winform

我是 C# 的新手。我试图在执行存储过程的同时将任务发送到 运行。因此,例如 - 我有一个存储过程,在这种情况下,它只是 运行ning WAITFOR DELAY '00:00:10'。在那十秒钟内,标签将填充文本,其中将添加句点,然后删除,就像您在加载屏幕中看到的那样。

正在禁用复制。 禁用复制.. 禁用复制...

一旦 proc 完成,它将跳出 while 循环。这是由布尔值处理的。所以 _IsRunning = false,运行 存储过程然后设置 IsRunning = true。如果我只使用我用于测试目的的 Thread.Sleep(1000) 而不是存储过程,代码将完全按照我想要的方式工作。

谁能告诉我为什么这在使用存储过程时不起作用?它只是卡在 while 循环中,并不断说正在加载完全停止的禁用复制。

using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsynchronousCoding
{
    public partial class Form1 : Form
    {
        private DataAccess _access = new DataAccess();


        public Form1()
        {
            InitializeComponent();
        }
        


        private async Task LoadRapport()
        {

            await DisableReplication();


        }


        private async Task DisableReplication()
        {
            Task.Factory.StartNew(TestMethod);
            await Task.Factory.StartNew(() => ShowProgressText("Disabling Replication"));
        }

        private bool _IsRunning;

        private void TestMethod()
        {
            _isRunning= false;
            //Thread.Sleep(10000);
            _access.Rapport_ReplicationSetting();
            _isRunning= true;
        }


        private void ShowProgressText(string txt)
        {
            var count = 0;
            var logText = new StringBuilder();

            logText.Append(txt);
            var baseLen = logText.Length;

            while (!_isRunning)
            {
                Thread.Sleep(250);
                if (count >= 3)
                {
                    logText.Remove(baseLen, count);
                    count = 0;
                }

                logText.Append(".");
                count++;

                BeginInvoke(new Action(() => { UpdateProgressText(logText.ToString()); }));

            }

            BeginInvoke(new Action(() => { UpdateProgressText(txt + " - Complete"); }));
            Thread.Sleep(2000);
        }
        private void UpdateProgressText(string txt)
        {
            lblProgress.Text = txt;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            LoadRapport();
        }
    }
}

考虑这个具有 CancellationToken 用法的简单示例。我不建议bool,不是Thread-safe。

private async void button1_Click(object sender, EventArgs e)
{
    IProgress<string> progress = new Progress<string>(s => lblProgress.Text = s);
    using (CancellationTokenSource cts = new CancellationTokenSource());
    {
        Task animationTask = ProgressAnimationAsync(progress, cts.Token);
        await DoSomeJobAsync();
        // await Task.Run(() => DoSomeHeavyJob()); // uncomment for test
        cts.Cancel();
        await animationTask;
    }
}

private async Task ProgressAnimationAsync(IProgress progress, CancellationToken token)
{
    int i = 1;
    while (!token.IsCancellationRequested)
    {
        progress.Report("Loading" + new string("." , i));
        i = i == 3 ? 1 : i + 1;
        await Task.Delay(250);
    }
}

// as I/O-bound operation
private async Task DoSomeJobAsync()
{
    await Task.Delay(10000);
}

// as CPU-bound operation
private void DoSomeHeavyJob()
{
    Thread.Sleep(10000);
}

有两种不同的方法,您可以同时进行测试。

注意:这里直接使用lblProgress.Text是安全的,没有IProgress同步回调。这里只是举个例子。在 UI 线程中创建 new Progress,您可以在没有 InvokeBeginInvoke.

的情况下从任何其他线程安全地调用 .Report()

您可以详细了解 X-bound 操作 here