我真的很喜欢这个问题:
在C#中执行fire and forget方法的最简单方法是什么?
我只是想知道,现在我们在C#4.0中有并行扩展,是否有更好的更简洁的方法来使用并行linq进行Fire&Forget?
我正在尝试在PHP中创建一个fire and forget方法,以便我可以将POST
数据发送到Web服务器而不必等待响应.我读到这可以通过使用CURL
以下代码中的类似来实现:
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_fields);
curl_exec($ch);
curl_close($ch);
Run Code Online (Sandbox Code Playgroud)
但是我不认为它像我期望的那样有效.例如,如果我发送请求的URL出错,则会导致我的脚本也抛出错误.如果它是火,忘记我会期望不会发生.
任何人都可以告诉我,我做错了什么或提供替代建议.我在本地和Linux上使用Windows进行开发,登台和生产环境.
UPDATE
我在这里找到了另一种解决方案:http://blog.markturansky.com/archives/205
我把它清理成下面的代码:
function curl_post_async($url, $params = array())
{
// create POST string
$post_params = array();
foreach ($params as $key => &$val)
{
$post_params[] = $key . '=' . urlencode($val);
}
$post_string = implode('&', $post_params);
// get URL segments
$parts = parse_url($url);
// workout port and open socket
$port = isset($parts['port']) ? $parts['port'] : 80;
$fp = …
Run Code Online (Sandbox Code Playgroud) 有人可以告诉我如何在Perl中解雇一个进程吗?我已经看过ruby:如何解雇并忘记子进程?在Ruby中做同样的事情.
我正在开发一个Web API项目,该项目使用Azure的托管缓存服务将数据库结果缓存到内存中,以缩短响应时间并减轻数据库的重复流量.尝试在缓存中放入新项时,有时会抛出特定于缓存的异常,代码为DataCacheErrorCode.RetryLater
.当然,为了以后重试而不需要阻止这种方法,我做了它async
并await Task.Delay
在稍后再试一次.以前,开发人员已经Thread.Sleep
在那里硬编码,这确实会损害应用程序性能.
方法签名看起来与此类似:
public static async Task Put(string cacheKey, object obj)
Run Code Online (Sandbox Code Playgroud)
在此更改之后,我从应用程序中的所有其他位置获得~75个编译器警告,这些警告调用以前的同步版本Put
指示:
因为不等待该调用,所以在调用完成之前继续执行当前方法.考虑将'await'运算符应用于调用的结果.
在这种情况下,由于Put
没有返回任何内容,因此我有理由让这个操作发生故障,因为我没有看到任何理由阻止执行调用它的方法.我只是想知道是否存在任何危险或陷阱,Task
因为Put
可以经常调用在后台运行许多这些即发即弃的操作.或者我应该等待,因为99%的时间我不会得到重试错误,并且Task
几乎立即完成.我只是想确保我没有因为有太多线程(或类似的东西)而受到任何处罚.
我编写了一个 API 来进行数据库调用并执行一些业务逻辑。我正在调用一个必须在后台执行某些操作的 goroutine。由于 API 调用不应等待此后台任务完成,因此我在调用 goroutine 后立即返回 200 OK(让我们假设后台任务永远不会给出任何错误。)
我读到,一旦 goroutine 完成其任务,goroutine 将被终止。这种一劳永逸的方式是否能避免 goroutine 泄漏?Goroutine 在执行任务后是否会终止并清理?
func DefaultHandler(w http.ResponseWriter, r *http.Request) {
// Some DB calls
// Some business logics
go func() {
// some Task taking 5 sec
}()
w.WriteHeader(http.StatusOK)
}
Run Code Online (Sandbox Code Playgroud) 我正在排队工作,在每项工作结束时,我想要启动一个SP,它将对数据进行大量处理.所以我不想等待SP完成,我只想在触发SP后立即转到下一个工作.存储过程将从触发代码中获取输入.
问题: -
这是我创建工作的脚本.请注意,我没有添加任何计划.
BEGIN TRANSACTION
DECLARE @ReturnCode INT
SELECT @ReturnCode = 0
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1)
BEGIN
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]'
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
END
DECLARE @jobId BINARY(16)
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'job_JobName',
@enabled=1,
@notify_level_eventlog=0,
@notify_level_email=0,
@notify_level_netsend=0,
@notify_level_page=0,
@delete_level=0,
@description=N'No description available.',
@category_name=N'[Uncategorized (Local)]',
@owner_login_name=N'UserName', @job_id = @jobId OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback
EXEC …
Run Code Online (Sandbox Code Playgroud) c# sql-server stored-procedures sql-server-2008 fire-and-forget
以下文字旨在扩展并为此问题添加颜色:
如何防止行为不端的客户端取消整个服务?
我基本上有这样的场景:一个WCF服务启动并运行一个客户端回调,具有直接,简单的单向通信,与此没有很大不同:
public interface IMyClientContract
{
[OperationContract(IsOneWay = true)]
void SomethingChanged(simpleObject myObj);
}
Run Code Online (Sandbox Code Playgroud)
我这个方法每秒可能会调用这种方法几千次,最终会有50个并发连接的客户端,延迟时间尽可能低(<15 ms会很好).这工作正常,直到我在连接到服务器的其中一个客户端应用程序上设置了一个断点,然后一切都挂起,可能2-5秒后服务挂起,其他任何客户端都没有收到任何数据大约30秒左右,直到服务注册连接故障事件并断开违规客户端.在此之后,所有其他客户端继续以愉快的方式接收消息.
我已经研究过serviceThrottling,并发性调整,设置线程池最小线程,WCF秘密酱和整个9码,但最后这篇文章MSDN - WCF要点,单向呼叫,回调和事件 完全描述了问题我没有真正提出建议.
允许服务安全地回调客户端的第三种解决方案是将回调契约操作配置为单向操作.即使并发设置为单线程,这样做也可以使服务回调,因为没有任何回复消息可以争用锁.
但是在文章的早些时候,它只是从客户的角度描述了我所看到的问题
当单向呼叫到达服务时,它们可能不会一次全部调度,并且可能在服务端排队等待一次一个地调度,所有这些都根据服务配置的并发模式行为和会话模式.服务愿意排队的消息(无论是单向消息还是请求 - 答复)是配置的信道和可靠性模式的产物.如果排队消息的数量超过了队列的容量,则客户端将阻止,即使在发出单向呼叫时也是如此
我只能假设反之亦然,到客户端的排队消息数超过了队列容量,并且线程池现在充满了试图调用此客户端的线程,这些线程现在全部被阻止.
处理这个问题的正确方法是什么?我是否应该研究一种方法来检查每个客户端在服务通信层排队的消息数量,并在达到某个限制后中止其连接?
几乎看来,如果WCF服务本身在队列填满时阻塞,那么每当一个客户端的队列满了时,我在服务中实现的所有异步/单向/即发即弃策略仍将被阻止.
我有一个异步方法:
public async Task DoSomethingAsync(){
...
await ...
await ...
....
return await SaveAsync();
}
Run Code Online (Sandbox Code Playgroud)
在大多数时候,我通过以下方式调用此方法:
await DoSomethingAsync()
Run Code Online (Sandbox Code Playgroud)
此调用按预期工作.但在某个地方,我需要将此方法称为火,并忘记:
public void OtherMethod()
{
...
DoSomethingAsync(); //fire and forget here
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,有时Task会DoSomethingAsync()
运行并完成,但有时候任务永远不会被调用(或调用某些await
内部DoSomethingAsync()
但从不完成最后一个await SaveAsync();
).
我正在尝试通过以下代码确保以火灾和忘记方式调用任务:
public void OtherMethod()
{
...
Task.Factory.StartNew(() =>
{
await DoSomethingAsync();
}); //fire and forget again here
}
Run Code Online (Sandbox Code Playgroud)
但是,这不符合预期.所以我的问题是:
如何拨打DoSomethingAsync()
无线电话await
将始终运行并完成?(我不关心AppDomain重启/崩溃的情况)
如果我删除所有async/await
代码DoSomethingAsync()
并替换await
为.ContinueWith()
,则调用Task DoSomethingAsync()
(不具有async
方法声明)将被调用并确定完成(忽略大小写AppDomain重启/崩溃),如果是,则从调用多长时间(我不如果在10分钟后调用任务,我会觉得我很开心)?
等待发送非必要指标对我来说毫无意义,因为它会在每次调用后端 dotnet 核心服务时增加延迟(等待服务器的响应),每次客户端调用可能会发生多次。尽管如此,在失败时记录错误仍然很重要(我不需要抛出它,因为指标的失败不应该影响服务)。
我找到了多种方法。这是以 FireAndForget 方式调用的方法:
public async Task FireAndForget()
{
try{ await sendTheMetric(); } // Try catch on the await, to log exceptions
catch(Exception e){ logger.debug(e) }
}
Run Code Online (Sandbox Code Playgroud)
方法一:去掉await。
FireAndForget(); // No await in front of the call
Run Code Online (Sandbox Code Playgroud)
方法 2:对我来说似乎类似于方法 1,因为我们不等待 Task.Factory.StartNew 调用。
Task.Factory.StartNew(async () => await MyAsyncTask());
Run Code Online (Sandbox Code Playgroud)
方法 3:作为工作项在 ThreadPool 上排队。
ThreadPool.QueueUserWorkItem(async o => await FireAndForget());
Run Code Online (Sandbox Code Playgroud)
我很难找到应该将哪个用于 Fire 并忘记调用发送非必要指标。我的目标是在每次发送指标时不增加对我的服务的每次调用的延迟。当指标发送失败时记录错误很重要,但它不应该重新抛出。线程上下文对于任务的执行并不重要。任务应该总是,或至少几乎总是,完成。
哪个是需求的最佳实践?还是他们都一样?
注意:我没有包含async void
,因为它看起来有风险(如果发生异常,它可能会崩溃,因为没有 Task 会包装它)。
我有一个长时间运行的同步 Python 程序,我希望每秒运行大约 10 个“即发即忘”任务。这些任务调用远程 API,不需要返回任何值。我尝试了这个答案,但它需要太多的CPU/内存来生成和维护所有单独的线程,所以我一直在研究asyncio。
这个答案很好地解释了如何使用 asyncio 运行“即发即忘”。但是,它需要使用 using run_until_complete()
,它会等待所有异步任务完成。我的程序使用同步 Python,所以这对我不起作用。理想情况下,代码应该像这样简单,log_remote
不会阻塞循环:
while True:
latest_state, metrics = expensive_function(latest_state)
log_remote(metrics) # <-- this should be run as "fire and forget"
Run Code Online (Sandbox Code Playgroud)
我使用的是Python 3.7。如何在另一个线程上使用 asyncio 轻松运行它?
fire-and-forget ×10
c# ×5
.net ×3
async-await ×3
asynchronous ×3
.net-4.0 ×1
.net-core ×1
asp.net-mvc ×1
concurrency ×1
curl ×1
go ×1
goroutine ×1
performance ×1
perl ×1
php ×1
post ×1
process ×1
python ×1
sql-server ×1
wcf ×1