C#线程问题

only_youlix 2021-02-25 06:05:22
c# 调用 c++库的一个方法Utils.Search。 这个方法内会阻塞线程60秒。将这个方法调用 放在线程中。怎么才能终止这个线程,终止后 不执行SetResult方法

th = new Thread(() =>
{
SetResult(Utils.Search(60));
});
th.IsBackground = true;
th.Start();
th.Abort();//终止线程



CancellationTokenSource cts = new CancellationTokenSource();
string res = "";
await Task.Run(() =>
{
timer.Start();
res = Utils.Search(60);
}, cts.Token);
if (!cts.IsCancellationRequested)
{
SetResult(res);
}


使用场景是 比如做扫码支付(微信和支付宝),生成微信二维码的同时 去调查询,在这期间又点击了支付宝二维码,所以就需要将查询微信的那个线程停止掉(想的思路是这样。但是线程又不是说停就停的。不知道怎么搞了。。),有啥好的解决方法吗
...全文
1042 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_41442872 2021-03-03
  • 打赏
  • 举报
回复
不太懂,就进来看看
only_youlix 2021-03-02
  • 打赏
  • 举报
回复
引用 10 楼 luj_1768 的回复:
运行权限?一般情况下,search(); 运行权限较低,却难以退出执行,应该会自动避让其他任务、待其他任务完成后会自动恢复运行;有时候,search(); 会运行在较高权限下,就会阻止其他程序运行、甚至致使界面停止响应;背后是由系统自动管理的。
这个阻塞UI线程 是因为 他那个c++方法里面 是循环查询(60s之内) ,我这边只能等待 有结果了之后 再进行后续操作
only_youlix 2021-03-02
  • 打赏
  • 举报
回复
引用 11 楼 xiaoxiangqing 的回复:
最好的办法是点了支付后,不允许用户再点支付,需要等待一段时间。
之前做遮罩了。不过扫码并没有回调通知。所以程序并不知道有没有扫码。要么等60s 要么扫码之后再取消支付。 所以只能做成 切换支付宝的之后,把微信那一笔交易 关闭了,然后阻止查询微信的那个线程结果执行。 准备搞成一码付或者被扫 就不用管这些了。。
xiaoxiangqing 2021-03-02
  • 打赏
  • 举报
回复
最好的办法是点了支付后,不允许用户再点支付,需要等待一段时间。
luj_1768 2021-03-02
  • 打赏
  • 举报
回复
运行权限?一般情况下,search(); 运行权限较低,却难以退出执行,应该会自动避让其他任务、待其他任务完成后会自动恢复运行;有时候,search(); 会运行在较高权限下,就会阻止其他程序运行、甚至致使界面停止响应;背后是由系统自动管理的。
only_youlix 2021-03-01
  • 打赏
  • 举报
回复
.net版本 是 wpf+.netframework4.5 和 .net5
only_youlix 2021-03-01
  • 打赏
  • 举报
回复
引用 6 楼 wanghui0380 的回复:
上面代码在netcore以上不能用(netcore不在支持Thread.Abort方法) 下面我就直接用CancelToken模拟一下你这个C++的同步阻塞封装
我测试了。改了一下。 每切换一下就把对应的cts设置为已取消,然后new一个cts 存到列表里。 那个c++方法写的是 http请求 轮询查询(60s)

   CancellationTokenSource cts;
   int num = 0;
   Dictionary<int, CancellationTokenSource> ctsList = new Dictionary<int, CancellationTokenSource>();
   async void SSearch(int num)
        {
            try
            {
                string res = await method(cts.Token);
                if (ctsList[num].IsCancellationRequested)
                {
                    Item.Add($"测试{num}结果:已取消");
                }
                else
                {
                    Item.Add($"测试{num}结果:{res}");
                }

            }
            catch (Exception e)
            {
                Item.Add($"测试{num}异常:" + e.Message);
            }
            finally
            {
                timer.Stop();
                Info = "等待支付...";
            }
        }
lythappy 2021-03-01
  • 打赏
  • 举报
回复
线程没有办法终止
wanghui0380 2021-02-28
  • 打赏
  • 举报
回复
上面代码在netcore以上不能用(netcore不在支持Thread.Abort方法) 下面我就直接用CancelToken模拟一下你这个C++的同步阻塞封装
  static async Task Main(string[] args)
        {

            CancellationTokenSource cts = new CancellationTokenSource();
            //测试一:

            try
            {

                cts.CancelAfter(TimeSpan.FromSeconds(2));//2秒后就取消
                string res = await method(cts.Token);
                Console.WriteLine($"测试一结果:{res}");
            }
            catch (Exception e)
            {//方法本身需要10秒,上面2秒后取消,会触发一个Canceled异常
                Console.WriteLine("测试一异常:" + e.Message);

            }

            //测试二
            try
            {
                cts = new CancellationTokenSource();
                string res = await method(cts.Token);
                //不做取消,会正常拿到结果
                Console.WriteLine($"测试二结果:{res}");
            }
            catch (Exception e)
            {
                Console.WriteLine($"测试二异常:"+e.Message);
            }



            Console.ReadKey();

        }
        //异步锁
        private static SemaphoreSlim slim = new SemaphoreSlim(1);
        static async Task<string> method(CancellationToken cts)
        {
            await slim.WaitAsync(); //异步加锁
            //同步值到异步值封装任务
            TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
            try
            {
                await Task.Run(() =>
                    {
                        string res = test(TimeSpan.FromSeconds(10));
                        tcs.TrySetResult(res);
                        slim.Release(); //释放异步锁
                    }
                    , cts);
            }
            catch (Exception e)
            {
                tcs.TrySetException(e);
            }
            finally
            {
                slim.Release();
            }

            return await tcs.Task;
        }

        //模拟一个C++同步阻塞调用
        static string test(TimeSpan time)
        {
            Thread.Sleep(time);
            return "end";

        }
wanghui0380 2021-02-26
  • 打赏
  • 举报
回复
异步锁 顺带你可以自己百度“幂等性” ps:结束方法我们不太想提供,因为我们无法确定C++那边写了保证,提供取消支持。所以正常开发不是停,而是等待上次结束
正怒月神 2021-02-26
  • 打赏
  • 举报
回复
我觉得这个就是 幂等验证的问题。
wanghui0380 2021-02-26
  • 打赏
  • 举报
回复
Async Task<string> method(CancellationToken cts )
{
TaskCompletionSource<string>tcs=new TaskCompletionSource<string>();
                 

Task.run( ()=>{

cts.Register(() => { //订阅注销事件

tcs.TrySetCanceled() ; //给一个Canceled信号给tcs,让tcs的task结束,并传递给调用方
Thread.CurrentThread.Abort(); //这句就是结束这个线程,理论上下这句会结束这个线程,同时会引发下面异常,当然我前面也说了,我不知道那边C++的是否能正确处理这种被强制取消的处理,所以前面我其实本不想给你说这种处理方式
});

try
 {
     string res = Utils.Search(60);
     tcs.TrySetResult(res);
}
catch(Exception ex)
{
  tcs.TrySetException(ex) //尝试给外面抛个异常,如果是上面注销事件触发的,因为前面已经抛了一个chanceled,所以这里消息其实被抛弃了
}


},cts)

retrun await tcs.Task;
}
wanghui0380 2021-02-26
  • 打赏
  • 举报
回复
那你这样 TaskCompletionSource<string>tcs=new TaskCompletionSource<string>(); tcs.TrySetResult(res) 这个可以防止多次提交值
only_youlix 2021-02-26
  • 打赏
  • 举报
回复
引用 1 楼 wanghui0380 的回复:
异步锁 顺带你可以自己百度“幂等性” ps:结束方法我们不太想提供,因为我们无法确定C++那边写了保证,提供取消支持。所以正常开发不是停,而是等待上次结束
可能是想的有点问题。。。加锁倒是可以。 那我 像 第二种写法那样。结束的时候 判断是否是取消状态,是的话不执行方法 应该也行得通吧。

110,539

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧