Could anyone point me in the right direction with this, I seem to loop around the web in vain...
private: System::Void loginButton_Click(System::Object^ sender, System::EventArgs^ e) {
mLogin* lgn;
string text = marshal_as<string>(subjectName->Text);
if (lgn->login(&text) == "Master")
{
delete this;
mSockServ server;
vMaster master;
Thread^ newThread = gcnew Thread(gcnew ThreadStart(master, &vMaster::ShowDialog));
newThread->Start();
//master.ShowDialog();
server.sockInit();
}
else if (lgn->login(&text) == "Slave")
{
delete this;
vSlave slave;
mSockClnt client;
Thread^ newThread = gcnew Thread(gcnew ThreadStart(client, &mSockClnt::sockInit));
newThread->Start();
//client.sockInit(text);
slave.ShowDialog();
}
else if (lgn->login(&text) == "No")
{
MessageBox::Show("Not a valid username or password");
}
}
I just want to start a new form in a new thread so it would run concurrently with a socket server or client which I would also like to start in a new thread. I can't seem to start neither the socket nor the form, this are my errors:
Error 1 error C3352: 'ShowDialog' : the specified function does not match the delegate type 'void (void)'
Error 2 error C3352: 'void mSockClnt::sockInit(std::string)' : the specified function does not match the delegate type 'void (void)'
although I made sure that sockInit is of type void...
Thank you.
Related
Hello, if i try to build this code here, ill get a error and dont know what to do.
void wxsocket_test_finalFrame::OnServerStart(wxCommandEvent& WXUNUSED(event))
{
// Create the address - defaults to localhost:0 initially
wxIPV4address addr;
addr.Service(3000);
// Create the socket. We maintain a class pointer so we can
// shut it down
m_server = new wxSocketServer(addr);
// We use Ok() here to see if the server is really listening
if (! m_server->Ok())
{
return;
}
// Set up the event handler and subscribe to connection events
m_server->SetEventHandler(*this, SERVER_ID);
m_server->SetNotify(wxSOCKET_CONNECTION_FLAG);
m_server->Notify(true);
}
void wxsocket_test_finalFrame::OnServerEvent(wxSocketEvent& WXUNUSED(event))
{
// Accept the new connection and get the socket pointer
wxSocketBase* sock = m_server->Accept(false);
// Tell the new socket how and where to process its events
sock->SetEventHandler(*this, SOCKET_ID);
sock->SetNotify(wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG);
sock->Notify(true);
}
void wxsocket_test_finalFrame::OnSocketEvent(wxSocketEvent& event)
{
wxSocketBase *sock = event.GetSocket();
// Process the event
switch(event.GetSocketEvent())
{
case wxSOCKET_INPUT:
{
char buf[10];
// Read the data
sock->Read(buf, sizeof(buf));
// Write it back
sock->Write(buf, sizeof(buf));
// We are done with the socket, destroy it
sock->Destroy();
break;
}
case wxSOCKET_LOST:
{
sock->Destroy();
break;
}
}
}
\wxsocket_test_finalMain.cpp|99|error: 'm_server' was not declared in this scope|
OS: Windows
Compiler: gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
im a bloody newbie and cant figure out what is happening here, someone has a clue ?
I'm trying to create an event aggregator in C++/CLI, I know that the valid syntax in C# would be as follows:
//C# code
public partial class Foo : UserControl, IView, IDisposable
{
private IEventAggregator _aggregator;
public Foo(IEventAggregator aggregator)
{
InitializeComponent();
this._aggregator = aggregator;
if (this._aggregator == null)
throw new Exception("null pointer");
_subToken =_aggregator.GetEvent<fooEvent>().Subscribe(Handler, ThreadOption.UIThread, false);
}
private SubscriptionToken _subToken = null;
private void Handler(fooEventPayload args)
{
//this gets run on the event
}
}
However directly converting this to C++/CLI gives the error "a pointer-to-member is not valid for a managed class" on the indicated line. Is there a workaround? I think it has something to do with how C# generates "Action".
//C++/CLI code
ref class Foo
{
public:
Foo(IEventAggregator^ aggregator)
{
void InitializeComponent();
this->_aggregator = aggregator;
if (this->_aggregator == nullptr)
throw gcnew Exception("null pointer");
//error in the following line on Hander, a pointer-to-member is not valid for a managed class
_subToken = _aggregator->GetEvent<fooEvent^>()->Subscribe(Handler, ThreadOption::UIThread, false);
private:
IEventAggregator ^ _aggregator;
SubscriptionToken ^ _addActorPipelineToken = nullptr;
void Handler(fooEventPayload^ args)
{
//this gets run on the event
}
}
You need to explicitly instantiate the delegate object, rather than allowing C# to do this for you.
_subToken = _aggregator->GetEvent<fooEvent^>()->Subscribe(
gcnew Action<fooEventPayload^>(this, &Foo::Handler), ThreadOption::UIThread, false);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Explicitly instantiate the delegate.
// ^^^^ Object to call the delegate on.
// ^^^^^^^^^^^^^ C++-style reference to the method.
While I have found many instances of this question on SO, none of the solutions I have implemented have solved my problem; hopefully you can help me solve this riddle. Note: This is my first foray into the world of COM objects, so my ignorance is as deep as it is wide.
As a beginning, I am using Adrian Brown's Outlook Add-In code. I won't duplicate his CalendarMonitor class entirely; here are the relevant parts:
public class CalendarMonitor
{
private ItemsEvents_ItemAddEventHandler itemAddEventHandler;
public event EventHandler<EventArgs<AppointmentItem>> AppointmentAdded = delegate { };
public CalendarMonitor(Explorer explorer)
{
_calendarItems = new List<Items>();
HookupDefaultCalendarEvents(session);
}
private void HookupDefaultCalendarEvents(_NameSpace session)
{
var folder = session.GetDefaultFolder(OlDefaultFolders.olFolderCalendar);
if (folder == null) return;
try
{
HookupCalendarEvents(folder);
}
finally
{
Marshal.ReleaseComObject(folder);
folder = null;
}
}
private void HookupCalendarEvents(MAPIFolder calendarFolder)
{
var items = calendarFolder.Items;
_calendarItems.Add(items);
// Add listeners
itemAddEventHandler = new ItemsEvents_ItemAddEventHandler(CalendarItems_ItemAdd);
items.ItemAdd += itemAddEventHandler;
}
private void CalendarItems_ItemAdd(object obj)
{
var appointment = (obj as AppointmentItem);
if (appointment == null) return;
try
{
AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
finally
{
Marshal.ReleaseComObject(appointment);
appointment = null;
}
}
Bits not relevant to adding appointments have been redacted.
I instantiate the CalendarMonitor class when I spool up the Add-in, and do the work in the AppointmentAdded event, including adding a UserProperty to the AppointmentItem:
private void ThisAddIn_Startup(object sender, EventArgs e)
{
_calendarMonitor = new CalendarMonitor(Application.ActiveExplorer());
_calendarMonitor.AppointmentAdded += monitor_AppointmentAdded;
}
private async void monitor_AppointmentAdded(object sender, EventArgs<AppointmentItem> e)
{
var item = e.Value;
Debug.Print("Outlook Appointment Added: {0}", item.GlobalAppointmentID);
try
{
var result = await GCalUtils.AddEventAsync(item);
//store a reference to the GCal Event for later.
AddUserProperty(item, Resources.GCalId, result.Id);
Debug.Print("GCal Appointment Added: {0}", result.Id);
}
catch (GoogleApiException ex)
{
PrintToDebug(ex);
}
finally
{
Marshal.ReleaseComObject(item);
item = null;
}
}
The error is thrown here, where I try to add a UserProperty to the AppointmentItem. I have followed the best example I could find:
private void AddUserProperty(AppointmentItem item, string propertyName, object value)
{
UserProperties userProperties = null;
UserProperty userProperty = null;
try
{
userProperties = item.UserProperties;
userProperty = userProperties.Add(propertyName, OlUserPropertyType.olText);
userProperty.Value = value;
item.Save();
}
catch (Exception ex)
{
Debug.Print("Error setting User Properties:");
PrintToDebug(ex);
}
finally
{
if (userProperty != null) Marshal.ReleaseComObject(userProperty);
if (userProperties != null) Marshal.ReleaseComObject(userProperties);
userProperty = null;
userProperties = null;
}
}
... but it chokes on when I try to add the UserProperty to the AppointmentItem. I get the ever-popular error: COM object that has been separated from its underlying RCW cannot be used. In all honesty, I have no idea what I'm doing; so I'm desperately seeking a Jedi Master to my Padawan.
The main problem here is using Marshal.ReleaseComObject for RCW's that are used in more than one place by the managed runtime.
In fact, this code provoked the problem. Let's see class CalendarMonitor:
private void CalendarItems_ItemAdd(object obj)
{
var appointment = (obj as AppointmentItem);
if (appointment == null) return;
try
{
AppointmentAdded(this, new EventArgs<AppointmentItem>(appointment));
}
finally
{
Marshal.ReleaseComObject(appointment);
After the event returns, it tells the managed runtime to release the COM object (from the point of view of the whole managed runtime, but no further).
appointment = null;
}
}
Then, an async event is attached, which will actually return before using the appointment, right at the await line:
private async void monitor_AppointmentAdded(object sender, EventArgs<AppointmentItem> e)
{
var item = e.Value;
Debug.Print("Outlook Appointment Added: {0}", item.GlobalAppointmentID);
try
{
var result = await GCalUtils.AddEventAsync(item);
This method actually returns here. C#'s async code generation breaks async methods at await points, generating continuation passing style (CPS) anonymous methods for each block of code that handles an awaited result.
//store a reference to the GCal Event for later.
AddUserProperty(item, Resources.GCalId, result.Id);
Debug.Print("GCal Appointment Added: {0}", result.Id);
}
catch (GoogleApiException ex)
{
PrintToDebug(ex);
}
finally
{
Marshal.ReleaseComObject(item);
Look, it's releasing the COM object again. No problem, but not optimal at all. This is an indicator of not knowing what is going on by using ReleaseComObject, it's better to avoid it unless proven necessary.
item = null;
}
}
In essence the use of ReleaseComObject should be subject to a thorough review of the following points:
Do I need to actually make sure the managed environment releases the object right now instead of at an indeterminate time?
Occasionally, some native objects need to be released to cause relevant side effects.
For instance, under a distributed transaction to make sure the object commits, but if you find the need to do that, then perhaps you're developing a serviced component and you're not enlisting objects in manual transactions properly.
Other times, you're iterating a huge set of objects, no matter how small each object is, and you may need to free them in order to not bring either your application or the remote application down. Sometimes, GC'ing more often, switching to 64-bit and/or adding RAM solves the problem in one way or the other.
Am I the sole owner of/pointer to the object from the managed environment's point of view?
For instance, did I create it, or was the object provided indirectly by another object I created?
Are there no further references to this object or its container in the managed environment?
Am I definitely not using the object after ReleaseComObject, in the code that follows it, or at any other time (e.g. by making sure not to store it in a field, or closure, even in the form of an iterator method or async method)?
This is to avoid the dreaded disconnected RCW exception.
I inherited a Silverlight 5 application. On the server side, it has a DomainContext (service) with a method marked as
[Invoke]
public void DoIt
{
do stuff for 10 seconds here
}
On the client side, it has a ViewModel method containing this:
var q = Context.DoIt(0);
var x=1; var y=2;
q.Completed += (a,b) => DoMore(x,y);
My 2 questions are
1) has DoIt already been activated by the time I attach q.Completed, and
2) does the return type (void) enter into the timing at all?
Now, I know there's another way to call DoIt, namely:
var q = Context.DoIt(0,myCallback);
This leads me to think the two ways of making the call are mutually exclusive.
Although DoIt() is executed on a remote computer, it is best to attach Completed event handler immediately. Otherwise, when the process completes, you might miss out on the callback.
You are correct. The two ways of calling DoIt are mutually exclusive.
If you have complicated logic, you may want to consider using the Bcl Async library. See this blog post.
Using async, your code will look like this:
// Note: you will need the OperationExtensions helper
public async void CallDoItAndDosomething()
{
this.BusyIndicator.IsBusy = true;
await context.DoIt(0).AsTask();
this.BusyIndicator.IsBusy = false;
}
public static class OperationExtensions
{
public static Task<T> AsTask<T>(this T operation)
where T : OperationBase
{
TaskCompletionSource<T> tcs =
new TaskCompletionSource<T>(operation.UserState);
operation.Completed += (sender, e) =>
{
if (operation.HasError && !operation.IsErrorHandled)
{
tcs.TrySetException(operation.Error);
operation.MarkErrorAsHandled();
}
else if (operation.IsCanceled)
{
tcs.TrySetCanceled();
}
else
{
tcs.TrySetResult(operation);
}
};
return tcs.Task;
}
}
I am calling a async method having a single parameter, It will return me the result according to parameter. I am calling that method more than one time with different parameter value, but in Completed event i am getting the same value for all.
client.ListAllLookupValuesByTypeCompleted += client_ListAllAddressFormatCompleted;
client.ListAllLookupValuesByTypeAsync("AddressFormat");
client.ListAllLookupValuesByTypeCompleted += client_ListAllPhoneFormatCompleted;
client.ListAllLookupValuesByTypeAsync("PhoneFormat");
void client_ListAllAddressFormatCompleted(object sender, ListAllLookupValuesByTypeCompletedEventArgs e)
{
cmbAddressFormat.ItemsSource = e.Result;
}
void client_ListAllPhoneFormatCompleted(object sender, ListAllLookupValuesByTypeCompletedEventArgs e)
{
cmbPhonePrintFormat.ItemsSource = e.Result;
}
But getting same value in e.Result.
any suggetions. Thanks.
Your method may return a different value based on the first parameter, but both handlers will be called at the same time every time, regardless of what you send it. If this is a standard webservice reference, then you should see an object userState parameter available for you and this can be used to determine what to do.
client.ListAllLookupValuesByTypeCompleted += client_ListAllLookupValuesCompleted;
client.ListAllLookupValuesByTypeAsync("AddressFormat", true);
client.ListAllLookupValuesByTypeAsync("PhoneFormat", false);
void client_ListAllLookupValuesCompleted(object sender, ListAllLookupValuesByTypeCompletedEventArgs e)
{
// e.UserState will either be false or true
if ((bool)e.UserState)
cmbAddressFormat.ItemsSource = e.Result;
else
cmbPhonePrintFormat.ItemsSource = e.Result;
}