我正在进行代码审查,我担心这种模式,在该代码中随处可见:
try
{
await DoSomethingAsync();
await DoSomethingElseAsync();
// and so on...
}
catch (OperationCanceledException)
{
// all good, user cancelled
// log and return
return;
}
// handle other particular exceptions
// ...
catch (Exception ex)
{
// fatal error, alert the user
FatalErrorMessage(ex);
}
Run Code Online (Sandbox Code Playgroud)
我关心的部分是处理OperationCanceledException。这段代码不应该也处理AggregateException和检查唯一的内部异常吗OperationCanceledException?
我知道Task.Wait或者Task.Result会抛出AggregateException这样的,而不是OperationCanceledException. 代码的作者向我保证她只使用async/awaitinside out 而从不使用Wait/Result. AggregateException因此,她不喜欢额外观察取消的想法。然而,我的观点是一些基于标准的TaskBCL API 仍然可以用 包装OperationCanceledException,AggregateException …
我的应用程序具有以下顶级代码(略有缩写):
def main():
# Some setup code ...
try:
asyncio.run(my_coroutine())
except Exception as e:
print("Exiting due to exception {}: {}".format(type(e).__name__, e))
print("Coroutine finished")
# Some cleanup code ...
print("Shutdown complete")
Run Code Online (Sandbox Code Playgroud)
在 Python 3.8 中asyncio.run永远不会完成,因此清理代码不会运行(并且不会打印关闭文本)。当应用程序应该退出时,它只是永远挂起。在 Python 3.7 中它运行良好。Python的3.6没有asyncio.run,但相当类似的代码loop.run_until_complete()和loop.close()工作过。
一些额外的上下文:设置和清理代码启动并优雅地退出使用threading.Thread. 正是这个线程实际上停止了主协程:它取消了协程(从技术上讲,它取消了在 内调用的另一个协程my_coroutine())loop.call_soon_threadsafe
例子:
with suppress(asyncio.CancelledError):
[await t for t in asyncio.all_tasks(loop=self.loop)
if t is not asyncio.current_task()]
Run Code Online (Sandbox Code Playgroud)
为了避免Task was destroyed but it is pending!警告,我必须在取消后等待任务,但等待它们会导致终端被垃圾邮件发送CancelledError。我知道它被取消了,但我不需要看到它。
使用contextlib.suppress此处会对取消产生负面影响吗?我可以避免看到取消的错误(或任务被破坏的警告而无需等待)的唯一其他方法是使用asyncio.wait而不是启动我的初始任务asyncio.gather。由于某种原因,wait似乎抑制了异常。我用了return_when=asyncio.FIRST_EXCEPTION一个wait又return_exceptions=True一个gather。但似乎无论我如何设置它们的关键字参数,都会打印异常,而不会gather打印异常。wait
我正在尝试使用android api中的AudioRecord类开发一个音频捕获应用程序,设置,如何使用MediaRecorder.AudioSource.MIC音频源,该应用程序可以工作,但是当我尝试使用回音消除时,设置一个MediaRecorder.AudioSource. VOICE_COMMUNICATION如何在创建AudioRecorder对象时抛出IllegalArgumentException,但我不知道为什么:
我的代码是:
private static final int SAMPLE_RATE = 16000;
private static final int BIT_ENCODING = AudioFormat.ENCODING_PCM_16BIT;
private static final int CHANNEL_CONFIGURATION = AudioFormat.CHANNEL_CONFIGURATION_MONO;
private int m_i32BufferSize;
private AudioRecord m_AudioRecorder;
public caudioCapture ()
{
super ();
m_i32BufferSize = AudioRecord.getMinBufferSize(SAMPLE_RATE, CHANNEL_CONFIGURATION, BIT_ENCODING);
//Create audio recorder object
try
{
m_AudioRecorder = new AudioRecord (MediaRecorder.AudioSource.VOICE_COMMUNICATION,SAMPLE_RATE,CHANNEL_CONFIGURATION,BIT_ENCODING,m_i32BufferSize);
}
catch (IllegalArgumentException e)
{
throw new IllegalArgumentException("Bad arguments on AudioRecorder creation", e);
}
Run Code Online (Sandbox Code Playgroud)
在我的Android清单中,我有:
uses-permission android:name ="android.permission.RECORD_AUDIO"
也许是因为我使用的是三星galaxy tab p1000并且它与Android 2.2一起运行?任何的想法?
非常感谢
POSIX为线程取消类型指定了两种类型:PTHREAD_CANCEL_ASYNCHRONOUS和PTHREAD_CANCEL_DEFERRED(设置pthread_setcanceltype(3))确定何时pthread_cancel(3)生效.通过我的阅读,POSIX手册页对这些内容并没有太多说明,但Linux手册页中有以下内容PTHREAD_CANCEL_ASYNCHRONOUS:
线程可以随时取消.(通常,它会在收到取消请求后立即取消,但系统不保证这一点.)
我很好奇系统的含义并不能保证这一点.我可以很容易地想象这种情况发生在多核/多CPU系统中(在上下文切换之前).但是单核系统呢:
pthread_setcancelstate(3))并取消类型设置为PTHREAD_CANCEL_ASYNCHRONOUS?时,我们是否可以立即取消线程?我主要对Linux(LinuxThreads/NPTL)感到好奇,但更普遍的是关于POSIX标准兼容的查看此取消业务的方式.
更新/澄清:这里真正的实际问题是在调用pthread_cancel()目标线程已启用取消并设置为键入的位置后立即销毁的资源的使用PTHREAD_CANCEL_ASYNCHRONOUS!所以关键在于:在这种情况下取消的线程是否有一个很小的可能性在上下文切换后继续正常运行(即使是很短的时间)?
感谢Damon的回答,减少了与下一个上下文切换相关的信号传递和处理问题.
更新2:我回答了我自己的问题,指出这是一个不好的问题,并且应该从根本上不同的概念层面解决基础程序设计.我希望这个"错误"的问题对于那些想知道异步取消的奥秘的人有用.
我读到了取消方法,但根据我的理解,它们都提供了对任务外部任务的控制,但是如果我想从内部取消任务.
例如,在这个伪代码中:
Task tasks = new Task(() =>
{
bool exists = CheckFromDB();
if (!exists)
break;
}
Run Code Online (Sandbox Code Playgroud)
我可以从内部取消任务吗?我得到的唯一想法是在任务中触发一个异常并从外部处理它,但是这不是一种方法.
我正在玩async-await和取消以获得更多关于此事的理解.为此,我做了以下控制台应用程序:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTest
{
class Program
{
private static CancellationTokenSource _cancellationTokenSource;
private static CancellationToken _cancellationToken;
static void Main(string[] args)
{
Console.CancelKeyPress += myHandler;
_cancellationTokenSource = new CancellationTokenSource();
_cancellationToken = _cancellationTokenSource.Token;
var task = DoWorkAsync(_cancellationToken).ContinueWith(ContinueMethod);
task.Wait();
Console.ReadLine();
}
protected static void myHandler(object sender, ConsoleCancelEventArgs args)
{
if (_cancellationToken.CanBeCanceled)
{
_cancellationTokenSource.Cancel();
}
args.Cancel = true;
}
static void ContinueMethod(Task task)
{
if (task.IsCanceled)
{
Console.WriteLine("The task was canceled");
}
if (task.IsCompleted)
{
Console.WriteLine("The task completed successfully"); …Run Code Online (Sandbox Code Playgroud) 再会!我正在为 WinForms UI 编写一个帮助程序库。开始使用 TPL async/await 机制并遇到这种代码示例的问题:
private SynchronizationContext _context;
public void UpdateUI(Action action)
{
_context.Post(delegate { action(); }, null);
}
private async void button2_Click(object sender, EventArgs e)
{
var taskAwait = 4000;
var progressRefresh = 200;
var cancellationSource = new System.Threading.CancellationTokenSource();
await Task.Run(() => { UpdateUI(() => { button2.Text = "Processing..."; }); });
Action usefulWork = () =>
{
try
{
Thread.Sleep(taskAwait);
cancellationSource.Cancel();
}
catch { }
};
Action progressUpdate = () =>
{
int i = 0;
while …Run Code Online (Sandbox Code Playgroud) 我正在制作一个桌面编程游戏,包括C++ 11,Qt 5.6(一旦V-Play支持它,很快就会有5.7)和QML.用户将能够编写任意代码来解决难题; 但是,代码应该完全沙箱化,并且不会导致应用程序其余部分出现问题.
所以我实例化了一个脚本引擎,它的环境我完全控制并通过它运行播放器的代码.我不会说什么脚本引擎,因为我不希望解决方案依赖于引擎(另外,我可能支持多种语言).当玩家点击"提交"时,我会异步运行脚本,以便游戏的其余部分仍然响应.
但这是我的问题:如果玩家的代码需要很长时间才能运行会发生什么?或者更糟糕的是,如果它是一个无限循环呢? 玩家在学习时会犯错误,所以"他们不应该这样做" 在这里不是一个有效的答案.
所以我只是让玩家随意终止他们的代码,很好. 但是,如何在不冒未定义的行为,内存泄漏,崩溃或其他可能对游戏产生负面影响的事情的情况下做到这一点?
相关的是以下内容:
QFutures 不支持.QtConcurrent::runQFuture::cancel有没有办法cancel在async从异步包调用的线程中使用?我可以看到你可以从线程外部取消它,但我想知道是否有一个cancelSelf :: IO ()函数可以阻止它自己的执行.我可以使用唯一的id生成和线程引用的共享Map来组合一些东西Async,线程本身可以引用它,但这看起来太多了.我可以逃避未被捕获的异常或其他什么吗?