C# 为什么在WaitAsync完成之前处理连接?
我对DBus的使用有问题C# 为什么在WaitAsync完成之前处理连接?,c#,async-await,dbus,manualresetevent,freedesktop.org,C#,Async Await,Dbus,Manualresetevent,Freedesktop.org,我对DBus的使用有问题 我试图通过几个动作按钮来获得一个通知泡泡 到目前为止,我已经能够让泡沫显现出来 retValue = await proxy.NotifyAsync( 并获取已在回调中按下的按钮 await proxy.WatchActionInvokedAsync 请参阅下面的代码 现在,由于通知在收到响应之前返回,所以我需要等待用户的响应(ManualResetEventSlim),然后再关闭连接 这造成了一个死锁,我通过切换到AsyncManualResetEvent解决了这
我试图通过几个动作按钮来获得一个通知泡泡 到目前为止,我已经能够让泡沫显现出来
retValue = await proxy.NotifyAsync(
并获取已在回调中按下的按钮
await proxy.WatchActionInvokedAsync
请参阅下面的代码
现在,由于通知在收到响应之前返回,所以我需要等待用户的响应(ManualResetEventSlim),然后再关闭连接这造成了一个死锁,我通过切换到AsyncManualResetEvent解决了这个问题 现在它工作了,有点-我得到了冒泡,如果选择了冒泡操作(如果在超时之前单击-目前未处理超时),我会得到响应,但我也在WatchActionInvokedAsync中的OneError回调中传递了一个异常 错误回调:无法访问已释放的对象。对象名称:
'Tmds.DBus.Connection' 为什么会出现这个错误
不应
等待notifyResponseReceived.WaitAsync()代码>在释放连接之前返回
什么可能导致此错误
除此之外,为什么异常有一个空的stacktrace
namespace NotificationTest
{
// https://devblogs.microsoft.com/pfxteam/building-async-coordination-primitives-part-1-asyncmanualresetevent/
public class AsyncManualResetEvent
{
private volatile System.Threading.Tasks.TaskCompletionSource<bool> m_tcs;
public AsyncManualResetEvent()
{
this.m_tcs = new System.Threading.Tasks.TaskCompletionSource<bool>();
}
public System.Threading.Tasks.Task WaitAsync()
{
return this.m_tcs.Task;
}
//public void Set()
//{
// this.m_tcs.TrySetResult(true);
//}
public void Set()
{
System.Threading.Tasks.TaskCompletionSource<bool> tcs = this.m_tcs;
System.Threading.Tasks.Task.Factory.StartNew(s => ((System.Threading.Tasks.TaskCompletionSource<bool>)s).TrySetResult(true),
tcs, System.Threading.CancellationToken.None, System.Threading.Tasks.TaskCreationOptions.PreferFairness, System.Threading.Tasks.TaskScheduler.Default);
tcs.Task.Wait();
}
public void Reset()
{
while (true)
{
System.Threading.Tasks.TaskCompletionSource<bool> tcs = this.m_tcs;
if (!tcs.Task.IsCompleted ||
System.Threading.Interlocked.CompareExchange(ref this.m_tcs, new System.Threading.Tasks.TaskCompletionSource<bool>(), tcs) == tcs)
return;
} // Whend
} // End Sub Reset
} // End Class AsyncManualResetEvent
class Program
{
// https://wiki.debianforum.de/Desktop-Notification_von_Systemservice_mittels_dbus
// https://cheesehead-techblog.blogspot.com/2009/02/five-ways-to-make-notification-pop-up.html
// https://wiki.debianforum.de/Desktop-Notification_von_Systemservice_mittels_dbus
// https://gist.github.com/ducin/6152106
// https://cweiske.de/tagebuch/DBus%20notify-send%20over%20network.htm
// dotnet dbus list services --bus system | grep NetworkManager org.freedesktop.NetworkManager
// dotnet dbus list objects --bus system --service org.freedesktop.NetworkManager
// dotnet dbus codegen --bus system --service org.freedesktop.NetworkManager
// cd ~/gitlab/Projects/NotificationTest/Tmds.DBus.Tool
// dotnet run codegen --bus system --service org.freedesktop.NetworkManager
// dotnet run codegen --bus session --service org.freedesktop.Notifications
private static async System.Threading.Tasks.Task<uint> SendNotification()
{
uint retValue = 666;
// System.Threading.ManualResetEventSlim notifyResponseReceived = new System.Threading.ManualResetEventSlim();
AsyncManualResetEvent notifyResponseReceived = new AsyncManualResetEvent();
Tmds.DBus.ObjectPath objectPath = new Tmds.DBus.ObjectPath("/org/freedesktop/Notifications");
string service = "org.freedesktop.Notifications";
using (Tmds.DBus.Connection connection = new Tmds.DBus.Connection(Tmds.DBus.Address.Session))
{
await connection.ConnectAsync();
Notifications.DBus.INotifications proxy = connection.CreateProxy<Notifications.DBus.INotifications>(service, objectPath);
// Task<IDisposable> WatchActionInvokedAsync(Action<(uint id, string actionKey)> handler, Action<Exception> onError = null);
await proxy.WatchActionInvokedAsync(
delegate ((uint id, string actionKey) id)
{
if (id.id != retValue)
{
System.Console.WriteLine("abort");
return;
}
System.Console.WriteLine("Dialog Id: {0}", id.id);
System.Console.WriteLine($"ActionKey: {id.actionKey}");
notifyResponseReceived.Set();
}, delegate (System.Exception ex)
{
System.Console.Write("Error callback: ");
System.Console.WriteLine(ex.Message);
System.Console.WriteLine(ex.StackTrace);
}
);
// string[] actions = new string[0];
string[] actions = new string[] { "0", "Cancel", "1", "No", "266789", "default", "3", "test" };
System.Collections.Generic.Dictionary<string, object> hints =
new System.Collections.Generic.Dictionary<string, object>();
string icon = "insert-image"; // # Siehe https://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html#names
icon = "call-start";
icon = "/root/Downloads/5d9ad698-8270-4141-b64e-736d3dbb9ecc.jpeg";
icon = "dialog-information";
icon = "dialog-error";
icon = "dialog-warning";
icon = "flag-ch";
// https://developer.gnome.org/notification-spec/
//await proxy.NotifyAsync("Notification", 0, icon, "summary", "body", actions, hints, 0);
retValue = await proxy.NotifyAsync("Notifica1tion", 0, icon, "This is the summary", "This is the body", actions, hints, 5000);
// notifyResponseReceived.Wait(); // blocks itselfs
await notifyResponseReceived.WaitAsync();
} // End Using connection
return retValue;
} // End Task SendNotification
static void Main(string[] args)
{
System.Console.Write("Notification ID: ");
System.Console.WriteLine(SendNotification().Result);
System.Console.ReadKey();
System.Console.WriteLine(" --- Press any key to continue --- ");
System.Console.ReadKey();
} // End Sub Main
} // End Class AsyncManualResetEvent
} // End Namespace NotificationTest
namespace NotificationTest
{
// https://devblogs.microsoft.com/pfxteam/building-async-coordination-primitives-part-1-asyncmanualresetevent/
公共类异步重置事件
{
私有易失性System.Threading.Tasks.TaskCompletionSource m_tcs;
公共异步手动重置事件()
{
this.m_tcs=new System.Threading.Tasks.TaskCompletionSource();
}
public System.Threading.Tasks.Task WaitAsync()
{
返回此.m_tcs.Task;
}
//公共无效集()
//{
//此.m_tcs.TrySetResult(true);
//}
公共无效集()
{
System.Threading.Tasks.TaskCompletionSource tcs=this.m_tcs;
System.Threading.Tasks.Task.Factory.StartNew(s=>((System.Threading.Tasks.TaskCompletionSource)s).TrySetResult(true),
tcs、System.Threading.CancellationToken.None、System.Threading.Tasks.TaskCreationOptions.PreferFairity、System.Threading.Tasks.TaskScheduler.Default);
Task.Wait();
}
公共无效重置()
{
while(true)
{
System.Threading.Tasks.TaskCompletionSource tcs=this.m_tcs;
如果(!tcs.Task.IsCompleted||
System.Threading.Interlocated.CompareeExchange(参考this.m_tcs,new System.Threading.Tasks.TaskCompletionSource(),tcs)=tcs)
返回;
}//何时
}//结束子重置
}//结束类AsyncManualResetEvent
班级计划
{
// https://wiki.debianforum.de/Desktop-Notification_von_Systemservice_mittels_dbus
// https://cheesehead-techblog.blogspot.com/2009/02/five-ways-to-make-notification-pop-up.html
// https://wiki.debianforum.de/Desktop-Notification_von_Systemservice_mittels_dbus
// https://gist.github.com/ducin/6152106
// https://cweiske.de/tagebuch/DBus%20notify-通过%20network.htm发送%20
//dotnet dbus列表服务--总线系统| grep NetworkManager org.freedesktop.NetworkManager
//dotnet dbus列表对象--总线系统--服务org.freedesktop.NetworkManager
//dotnet dbus codegen--总线系统--服务org.freedesktop.NetworkManager
//cd~/gitlab/Projects/NotificationTest/Tmds.DBus.Tool
//dotnet运行codegen--总线系统--服务org.freedesktop.NetworkManager
//dotnet运行codegen--总线会话--服务org.freedesktop.Notifications
私有静态异步System.Threading.Tasks.Task SendNotification()
{
uint-retValue=666;
//System.Threading.ManualResetEventSlim notifyResponseReceived=新的System.Threading.ManualResetEventSlim();
AsyncManualResetEvent notifyResponseReceived=新的AsyncManualResetEvent();
Tmds.DBus.ObjectPath ObjectPath=new Tmds.DBus.ObjectPath(“/org/freedesktop/Notifications”);
string service=“org.freedesktop.Notifications”;
使用(Tmds.DBus.Connection Connection=newtmds.DBus.Connection(Tmds.DBus.Address.Session))
{
等待连接。ConnectAsync();
Notifications.DBus.INotifications proxy=connection.CreateProxy(服务,objectPath);
//任务WatchActionInvokedAsync(操作处理程序,操作onError=null);
等待proxy.WatchActionInvokedAsync(
委托((uint id,string actionKey)id)
{
如果(id.id!=retValue)
{
系统控制台写入线(“中止”);
返回;
}
System.Console.WriteLine(“对话框Id:{0}”,Id.Id);
System.Console.WriteLine($“ActionKey:{id.ActionKey}”);
notifyResponseReceived.Set();
},委托(System.Exception ex)
{
System.Console.Write(“错误回调:”);
系统控制台写入线(例如消息);
系统控制台写入线(例如StackTrace);
}
);
//string[]actions=新字符串[0];
字符串[]操作=新字符串[]{“0”、“取消”、“1”、“否”、“266789”、“默认”、“3”、“测试”};
System.Collections.Generic.Dictionary提示=
新的System.Collections.Generic.Dictionary();
string icon=“插入图像”/#Siehehttps://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html#names
icon=“呼叫开始”;
icon=“/root/Downloads/5d9ad698-8270-4141-b64e-736d3dbb9ecc.jpeg”;