SAS是否有像Java这样的并发框架(Does SAS have a concurrency framework like Java)
在Java中,您有一个并发框架,开发人员可以使用它来并行提交多个任务,其中每个任务都在自己的线程中运行。
SAS中是否存在类似的并发框架,开发人员可以在不同的线程中提交并行作业或程序?
In Java,you have a concurrency framework that the developer can use to submit multiple tasks in parallel where each task runs in its own thread.
Does a similar concurrency framework exist in SAS where developer can submit parallel jobs or programs in different threads?
原文:https://stackoverflow.com/questions/32303289
最满意答案
这是问题:
answer = MyQuestion(question).Result;
。在
Task
上使用Result
意味着“得到结果,但如果它还不可用,请等待 - 即阻止线程等待结果”。由于
MyQuestion
等待来自TaskCompletionSource
的Task
应该完成QuestionManager
或其他UI代码,而QuestionManager
(通过Result
)正在等待MyQuestion
完成,所以你有一个死锁!QuestionManager
阻止了UI线程,因此tcs
无法通过下一行或任何其他运行的UI代码接收结果。将
Result
更改为await
它,这将消失。 我不确定其余的逻辑是否会保持在一起,但这就是为什么在运行您发布的代码时UI会锁定的答案。
至于如何解决这个问题:这些都不需要任何异步等待。 使用异步会掩盖您实际想要编写的代码,并且您正在使用
async void
方法,这几乎总是一个坏主意 。我要做的是有一个具有问题和答案属性的类,保留所有剩余问题和答案的列表,并且每当提交新答案时始终对该列表中的第一项起作用,以查看答案是否为正确 - 您将知道是否显示“错误答案”并让他们再次尝试或是否进入下一个问题。
例如:
class QuestionAndAnswer { public string Question { get; set; } public string Answer { get; set; } } private List<QuestionAndAnswer> _currentQuestions; // create this list when loading everything private int _currentQuestionIndex = 0; // points to which element/index in the list contains the question shown on screen // call this once after you have loaded _currentQuestions with your data public void ShowCurrentQuestion() { var currQuestion = _currentQuestion[_currentQuestionIndex]; computerQuestionLabel.Text = currQuestion.Question; answerTextBox.Text = ""; } // call this from whichever event handler means that the user has // submitted an answer - an Answer button's Click event, maybe // answerTextBox's KeyPress event or something else. public void CheckForAnswer() { var currentAnswer = answerTextBox.Text; var currQuestion = _currentQuestion[_currentQuestionIndex]; if (currQuestion.Answer == currentAnswer) { // correct var nextQuestionIndex = _currentQuestionIndex + 1; if (nextQuestionIndex == _currentQuestion.Count) { // all questions answered! do the appropriate thing } else { // still questions left, show the next one _currentQuestionIndex = nextQuestionIndex; ShowCurrentQuestion(); } } else { // wrong answer; the question that needs to be shown is // already shown, you can handle "stop" or other things here } }
这里有一个自然事件,意思是“有人刚刚提交了一个新答案”,您可以将其用作漏斗点。 没有必要编写等待新答案的代码。 通过编写使事件响应用户事件而发生的代码,您已经实际上异步处理(做你的事情,等待用户做某事,做更多事情),这只是你没有使用
async
/await
/Task
s或显式编写异步代码来完成它。This is the issue:
answer = MyQuestion(question).Result;
.Using
Result
on aTask
means "get me the result, but if it's not yet available, wait - ie block the thread waiting for the result of this".Since
MyQuestion
waits for theTask
from aTaskCompletionSource
thatQuestionManager
or other UI code is supposed to complete, andQuestionManager
(throughResult
) is waiting forMyQuestion
to finish, you have a deadlock!QuestionManager
is blocking the UI thread, sotcs
can't receive a result either through the next line or through any other UI code running.Change
Result
toawait
ing it, and this will go away. I am not certain that the rest of the logic will hold together, but this is the answer to why the UI locks up when you run the code you posted.
As for how to solve this: none of this actually requires any asynchronous waiting. Using asynchrony obscures the code you actually want to write, and you're using
async void
methods which is nearly always a bad idea.What I would do is have a class with properties for a question and an answer, keep a list of all remaining questions-and-answers and always work against the first item in that list whenever a new answer is submitted to see if the answer is correct - you'll know whether to show "wrong answer" and have them try again or whether to advance to the next question.
For example:
class QuestionAndAnswer { public string Question { get; set; } public string Answer { get; set; } } private List<QuestionAndAnswer> _currentQuestions; // create this list when loading everything private int _currentQuestionIndex = 0; // points to which element/index in the list contains the question shown on screen // call this once after you have loaded _currentQuestions with your data public void ShowCurrentQuestion() { var currQuestion = _currentQuestion[_currentQuestionIndex]; computerQuestionLabel.Text = currQuestion.Question; answerTextBox.Text = ""; } // call this from whichever event handler means that the user has // submitted an answer - an Answer button's Click event, maybe // answerTextBox's KeyPress event or something else. public void CheckForAnswer() { var currentAnswer = answerTextBox.Text; var currQuestion = _currentQuestion[_currentQuestionIndex]; if (currQuestion.Answer == currentAnswer) { // correct var nextQuestionIndex = _currentQuestionIndex + 1; if (nextQuestionIndex == _currentQuestion.Count) { // all questions answered! do the appropriate thing } else { // still questions left, show the next one _currentQuestionIndex = nextQuestionIndex; ShowCurrentQuestion(); } } else { // wrong answer; the question that needs to be shown is // already shown, you can handle "stop" or other things here } }
There's a natural event here meaning "someone just submitted a new answer", and you can use that as a funnel point. There's no need to write code that waits for new answers. By writing code that makes things happen in response to user events, you are already in effect doing things asynchronously (do your stuff, wait for the user to do something, do even more stuff), it's just that you're not using
async
/await
/Task
s or writing explicitly asynchronous code to do it.
相关问答
更多-
在C#和C ++之间异步通信与C#应用程序的两个部分之间异步通信没有什么不同 - 您最终在最后调用一个不同的函数 - 也就是说,C#的delegate类型将变成C ++最终提供的函数指针.NET JIT。 这被称为反向P / Invoke,并允许非托管C ++调用.NET代码。 Communicating asynchronously between C# and C++ is no different to communicating asynchronously between two parts of ...
-
数据库查询和写入文件都是I / O绑定操作,因此它们非常适合async和await 。 首先,您将定义KuliMon.Export的异步版本: async Task
ExportAsync() { var data = await myQuery.ToListAsync(); await myStream.WriteAsync(...); return results; } 例如,您可以使用Entity Framework 6进行异步查询支持 。 然后你可以从你的UI中调用 ... -
在C#中以异步方式创建新的DocumentDB文档的问题(Problems for create new DocumentDB documents in async in C#)[2023-06-06]
正确,你有一个经典的异步阻止另一个异步的情况。 您应该在等待ScannedCode.AddAsync()时将ConfigureAwait设置为false; await ScannedCode.AddAsync().ConfigureAwait(false); 这使它在线程池线程而不是ASP.NET请求上下文上恢复。 您可以阅读以下文章http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html ,它可以很好地解释这一点以及使用异步 ... -
Unity C#问题(Unity C# Problems)[2021-07-04]
你可能想写inventory.ItemID = 1; 而不是Inventory.ItemID = 1; 。 也就是说,如果你想设置player.GetComponent();的结果的ItemId player.GetComponent (); 到1。 您正尝试在类Inventory上调用方法而不是在对象inventory上调用方法,并且如果方法不是静态的,则无法理解。 You probably want to write inventory.ItemID = 1; ... -
C#中的异步套接字(Asynchronous sockets in C#)[2023-01-29]
如果我们只使用单个套接字,那么将状态传递给BeginReceive方法有什么意义呢? 是否要避免使用类字段? 这样做似乎没什么意义,但也许我错过了一些东西。 你是对的,如果你没有使用状态,那么你必须使用一个成员。 但这不是一个状态变量本地。 本地事物越多,当您在代码的其他部分进行更改时,它们破坏的可能性就越小。 将它与普通方法调用进行比较。 为什么我们不将参数设置为成员,然后调用所有函数而不使用任何参数? 它会工作......但阅读代码会很糟糕。 通过将范围尽可能保持在本地,可以使设计更易于理解和修改。 改 ... -
C#中的异步问题(Asynchronous problems in C#)[2022-12-29]
这是问题: answer = MyQuestion(question).Result; 。 在Task上使用Result意味着“得到结果,但如果它还不可用,请等待 - 即阻止线程等待结果”。 由于MyQuestion等待来自TaskCompletionSource的Task应该完成QuestionManager或其他UI代码,而QuestionManager (通过Result )正在等待MyQuestion完成,所以你有一个死锁! QuestionManager阻止了UI线程,因此tcs无法通过下一行或任 ... -
c#异步服务器回复(c# asynchronous server reply)[2021-10-23]
你在哪里调用DisplayText cSocket.BeginSend怎么样? 显然能够使用BeginSend ,您需要将文本放入缓冲区。 有多种方法可以有效地完成它,但它超出了这个答案的范围。 但是如果您期望某种结构化数据(例如由换行符分隔的字符串),那么最好使用StreamReader.ReadLine 。 如果结构更复杂,那么您需要自己从缓冲区进行解析。 所以你需要从缓冲区中消耗一个字符,看看你是否有足够的数据,如果没有消耗,直到缓冲区为空。 当缓冲区为空时,您需要通过调用BeginReceive再次 ... -
C#中的斜杠和转义问题(Slash and Escape Problems in C#)[2022-02-27]
显然workSheet.SaveAs()做了自己的路径验证和修复。 所以你(正当地)因使用无效格式而受到惩罚。 这种格式通常被接受,但“通常”与“始终”不同。 Apparently workSheet.SaveAs() does its own validation and fix-up of the path. So you are (rightfully) being punished for using an invalid format. That format is usually accepte ... -
不,这是一个普遍的错误,并不是特定于异步代码。 在你的情况下,你可能更容易字节,因为你永远不会有[DllImport]背后的机器让你摆脱困境。 我会解释为什么会出错,也许这会有所帮助。 总是需要一个回调方法的委托声明,这就是CLR现在知道如何调用该方法。 您经常使用delegate关键字明确声明它,如果非托管代码是32位,您可能需要应用[UnmanagedFunctionPointer]属性,并假设该函数是用C或C ++编写的。 声明很重要,这就是CLR如何知道您从本机代码传递的参数如何转换为其托管等效项。 ...
-
select和poll有两个问题: 它们通常以单线程方式使用。 由于这个原因,它们无法扩展。 它们需要通过执行轮询的中心位置调度所有IO。 能够只指定在完成时神奇地调用的回调要好得多。 这会自动扩展,并且没有需要调度的中心位置。 .NET中的异步IO完全没有麻烦。 它只是有效(高效)。 Windows上的Async IO是无线程的。 当IO正在运行时,没有一个线程忙于提供它。 .NET中的所有异步IO都使用操作系统支持的真正异步IO。 这意味着重叠的IO或完成端口。 查看async / await,它也可以 ...