Contract function with transaction - c#

I have a question about programming VB.NET & Nethereum.
The contract address works flawlessly. For testing purposes I have built in a maintrace - pause function that can be set via function.
In the Remix tool + Metamask, the pause and resume function works perfectly.
I've been desperately looking for a solution for VB.NET (or else C #) for days:
The contract function (i have for test remove OnlyOwner variable in this Contract):
function SetPause() external returns (string memory) {
if (paused) {
paused = false;
emit Unpause();
Unpause;
return "Pause Set inactive";
} else {
paused = true;
Pause;
emit Pause();
return "Pause Set active";
}
}
When I address the function via VB.NET I get the return messages as normal, but my wallet does not carry out a transaction. Thus the status does not change. Other functions like transfer. Query of token names and balance work fine.
The VB.NET code:
Dim changeFunction As Task(Of String) = Contract.GetFunction("SetPause").SendTransactionAsync(senderAddress, gas)
changeFunction.Wait()
Textbox1.Text = changeFunction.Result
As I said, I get all the correct feedback, but no transactions are carried out (changes), only read queries. I also tried other VB.NET codes. Unsuccessful ...

Related

Why does my app crash when a button is clicked?

I am trying to make a friends function into my Unity game. Each friend will have their own line with their name and a few buttons (challenge, about, etc.).
I have a friend row prefab and I instantiate it into the parent list for each friend.
It works just fine, until I click the challenge button, which whould call a method that takes in two parameters: the UId of the friend, and their username (two strings).
I am using Firebase Realtime Database for database.
void RetrieveFriendList(object sender, ValueChangedEventArgs args) {
foreach(Transform childTransform in listParent.GetComponentInChildren<Transform>()) {
GameObject.Destroy(childTransform.gameObject);
}
friends.Clear();
foreach (DataSnapshot s in args.Snapshot.Children) {
friends.Add(s.Key);
GameObject newRow = Instantiate(friendRowPrefab);
newRow.transform.Find("Deny").gameObject.GetComponent<Button>().onClick.RemoveAllListeners();
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.RemoveAllListeners();
newRow.transform.SetParent(listParent.transform);
newRow.transform.localScale = new Vector3(1f, 1f, 1f);
newRow.transform.Find("Text_Name").gameObject.GetComponent<TMPro.TMP_Text>().text = s.Child("username").Value.ToString();
string retrievedStatus = s.Child("type").Value.ToString();
if (retrievedStatus == "sent") {
newRow.transform.Find("Status").gameObject.GetComponent<TMPro.TMP_Text>().text = "Friend request sent";
} else if (retrievedStatus == "request") {
newRow.transform.Find("Status").gameObject.GetComponent<TMPro.TMP_Text>().text = "Incoming friend request";
newRow.transform.Find("Accept").gameObject.SetActive(true);
newRow.transform.Find("Deny").gameObject.SetActive(true);
newRow.transform.Find("Accept").gameObject.GetComponent<Button>().onClick.AddListener(delegate { AcceptFriendRequest(s.Key); });
newRow.transform.Find("Deny").gameObject.GetComponent<Button>().onClick.AddListener(delegate { DenyFriendRequest(s.Key); });
} else if (retrievedStatus == "friends") {
newRow.transform.Find("Challenge").gameObject.SetActive(true);
Debug.Log(s.Key + " - " + s.Child("username").Value.ToString());
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.AddListener(delegate { ChallengeFriend(s.Key, s.Child("username").Value.ToString()); }); //this is the line that causes the crash
newRow.transform.Find("About").gameObject.SetActive(true);
newRow.transform.Find("Status").gameObject.SetActive(false);
}
}
FirebaseDatabase.DefaultInstance.GetReference("users").Child(auth.CurrentUser.UserId).Child("friends").ValueChanged -= RetrieveFriendList;
}
What's likely happening is that the underlying C++ representation of your database snapshot is being cleaned up before your button accesses it. See this bug.
The easiest thing to do would be to find this line:
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.AddListener(delegate { ChallengeFriend(s.Key, s.Child("username").Value.ToString()); }); //this is the line that causes the crash
and turn it into something like:
var challengeKey = s.Key;
var challengeUsername = s.Child("username").Value.ToString();
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.AddListener(delegate { ChallengeFriend(challengeKey, challengeUsername); });
This way you retrieve the values you need (key and username) at the time of the callback rather than in the context of the button click (at some arbitrary point in the future after this function has returned). If you still get a crash, you may have to .Clone or .CopyTo the data -- but I believe that once an object is retrieved from the underlying snapshot it should be a full on C# object obeying the expected C# GC rules.
You also may experience null reference exceptions if the snapshot hits a local cache first -- so make sure you have null checks around everything (generally a good practice whenever you're hitting the web).

Handling Firebase "Tasks" and implement Manager Classes (for Firebase) in Unity

I'm writing the code for a game whose server-side is totally based on Firebase. I expect to use Auth, Database, InstanceID, Messaging and Cloud Functions in the game.
Being a novice C# Programmer, I encountered with C# "Tasks" first time with Firebase.
I'm going to use Database for a lot of times (like Score Update, Friends Requests, Chat, Friend Did this, Friend Did that).
I mostly feel comfortable with Singleton Pattern (GameManagers, EnemyManagers, SoundManagers etc..).
But with Firebase, since most of its calls are asynchronous and implemented via Tasks. I think I need to workaround differently to implement Managers.
For example, I need to send a Friend Request to a specific friend. The UIManager is a script that deals with UI events etc. I'd like to call Method from this script to another Manager (say FriendsManager). But I need to first check if this friend is already friend of mine from Database or Not? So, what I would do is
class UIManager
{
void OnFriendRequestClicked(string friendId)
{
bool userExists = FriendsManager.instance.UserExists(friendId);
if(userExists)
// Proceed with Sending Request
FriendsManager.instance.SendRequest(friendId);
else
// Show a Dialogue that User ID is invalid
ShowError("User Id is invalid");
// NOTE: The above code block of "condition" is executed before
// the UserID is validated from FriendsManager
// I know its because of Task. But how can I alter this code
// to do something in the similar pattern?
}
}
class FriendsManager
{
bool UserExists(string userIdToCheck)
{
reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(
task=>
{
if(task.IsCompleted)
{
if(task.Result == null)
return false; // (expected) Return false to Method "UserExists"
else
return true; //(expected) Return true to Method "UserExists"
// But this won't actually return "bool" to the method,
// it actually returns to its own "Task"
//NOTE: -> How to Return from here to the Method?
)};
}
Data is loaded from Firebase asynchronously. Instead of waiting/blocking while the data is being loaded, the app continues. And then when the data is available, it calls your callback.
You can most easily see this with some logging statements:
Debug.Log("Before starting to load data");
reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(task=> {
Debug.Log("Data loaded");
});
Debug.Log("After starting to load data");
When you run this code it logs:
Before starting to load data
After starting to load data
Data loaded
That is probably not what you expected, but explains perfectly why you can't return a value from within the callback: the UserExists has already finished at that point.
This means that any code that needs access to the data from the database, must be inside the ContinueWith block (or be called from there).
The simplest approach is to move the code from your OnFriendRequestClicked into UserExists:
bool UserExists(string userIdToCheck) {
reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(task=>
{
if(task.IsCompleted)
{
if(task.Result == null)
ShowError("User Id is invalid");
else
FriendsManager.instance.SendRequest(friendId);
)};
}
You can then call this function without the if after it.
The above approach works great, but means that your UserExists method is no longer reusable in different cases. To make it reusable again, you can pass your own callback interface into UserExists.
For example, using Task:
bool UserExists(string userIdToCheck, Action<bool> callback) {
reference.Child("users").Child(userIdToCheck).GetValueAsync().ContinueWith(task=>
{
if(task.IsCompleted)
{
if(task.Result == null)
callback(false);
else
callback(true);
)};
}
And then to invoke it:
FriendsManager.instance.UserExists(friendId, userExists => {
if(userExists)
FriendsManager.instance.SendRequest(friendId);
else
ShowError("User Id is invalid");
})

How to check ALL methods are true before performing an action

I have an issue in that I'm implementing approximately 5 validation checks in a form. Each of these is located in its own method Is_XXX_Valid(). I'm looking for a way to establish that each of the methods return true; otherwise an error message should be displayed.
This however is where the problem arises, I have a solution which works partially, in that it fails to run the subsequent methods if a previous method has returned false
Here is the current code which I am using:
private void Button_Click(object sender, EventArgs e)
{
DialogResult validation_msgbox = MessageBox.Show("Are you sure you would like to submit this form?", "Submit Form?", MessageBoxButtons.YesNo);
// Run each validaion check
if (IsAAAValid() && IsBBBValid())
{
//Continue and submit data
}
else
{
//Display the errors
DialogResult Textbox_validation = MessageBox.Show(ErrorText, "Some errors were found.", MessageBoxButtons.OK);
}
}
Using the code above as an example, if IsAAAValid() returns false, then the second method is not executed and therefore the data within is not validated, leading to an incorrect dialog box if multiple errors are found.
Thanks!
This is known as "short-circuit evaluation," which you can read about here and is a usually-desirable feature of the C# programming language. You can get around it with something like this:
bool avalid = IsAAAValid();
bool bvalid = IsBBBValid();
if (avalid && bvalid)
{
//Continue and submit data
}
This will guarantee that both methods get run.
As a side note, for clarity in your code I would recommend that you rename your validation methods to signify that they have side-effects. That is, they do more than simply returning the state of the data; they actually have the potential to modify state. This is why short-circuit evaluation causes problems in this instance.
As adv12 has answered, this is called short-circuit evaluation but there is also an alternative to the way he refactored your code.
There are two boolean and operators:
&& - short-circuit evaluation
& - full evaluation
So you can simply switch to using & to call both methods regardless:
if (IsAAAValid() & IsBBBValid())
^
|
+-- only one &, not two &&
Now, having said that, personally I would write the code as adv12 did as it makes for easier to read code, not as easy to spot the use of only the one & but I thought I would post the answer for completeness.
You could simply call every method and sets a boolean value to false if any of the methods return false. At the end you could check this boolean value and display your error message.
bool isValid = true;
if(!IsValidA()) isValid = false;
if(!IsValidB()) isValid = false;
if(!IsValidC()) isValid = false;
if(!IsValidD()) isValid = false;
if(!IsValidE()) isValid = false;
if(!isValid)
MessageBox.Show("Global validation error message");
However I prefer a better approach in which you use a List<string> to accumulate error messages and print them all at the end
List<string> errors = new List<string>();
if(!IsValidA()) errors.Add("Fail on IsValidA");
if(!IsValidB()) errors.Add("Fail on IsValidB");
if(!IsValidC()) errors.Add("Fail on IsValidC");
if(!IsValidD()) errors.Add("Fail on IsValidD");
if(!IsValidE()) errors.Add("Fail on IsValidE");
if(errors.Count > 0)
{
string message = string.Join(Environment.NewLine, errors.ToArray());
MessageBox.Show("Validation errors found:" + Environment.NewLine + message);
}
I think this is better from a user perspective because you could inform her/him of the problems found in a single message and avoid that horrible user experience that happens when you tell to your user about a single problem, the user fixes the problem only to be awarded with another error message about another problem.

Handle a function taking a lot of time Threading

I have a function which is taking a lot of time to execute in a web application.
I have tested this with a profiler and by my logging.
I have other functions running in the same pageload.
What is a best way to display the rest of the values from those functions and keep this function in a thread and display it in a label when it finishes?
This function is used to get events in application which takes time.
private void getEventErrors()
{
EventLog eventLog = new EventLog("Application", ".");
getEvents(eventLog.Entries);
}
private void getEvents(EventLogEntryCollection eventLogEntryCollection)
{
int errorEvents = 0;
foreach (EventLogEntry logEntry in eventLogEntryCollection)
{
if (logEntry.Source.Equals("XYZ"))
{
DateTime variable = Convert.ToDateTime(logEntry.TimeWritten);
long eventTimeTicks = (variable.Ticks);
long eventTimeUTC = (eventTimeTicks - 621355968000000000) / 10000000;
long presentDayTicks = DateTime.Now.Ticks;
long daysBackSeconds = ((presentDayTicks - 864000000000) - 621355968000000000) / 10000000;
if (eventTimeUTC > daysBackSeconds)
{
if (logEntry.EntryType.ToString() == "Error")
{
errorEvents = errorEvents + 1;
}
}
}
}
btn_Link_Event_Errors_Val.Text = errorEvents.ToString(GUIUtility.TWO_DECIMAL_PT_FORMAT);
if (errorEvents == 0)
{
lbl_EventErrorColor.Attributes.Clear();
lbl_EventErrorColor.Attributes.Add("class", "green");
}
else
{
lbl_EventErrorColor.Attributes.Clear();
lbl_EventErrorColor.Attributes.Add("class", "red");
}
}
I have 3 functions in the pageload event, two to get the values from the DB and the other one is shown above.
Should both these functions be service calls?
What i wanted was, the page should load fast and if there is a function taking a lot of time it should run in the background and display when done and in the process if the user want to navigate to a new page it should kill it and move on.
If you have a function that is running in a separate thread in ASP.NET, you may want to consider moving it to a service. There are many reason for this
See this answer (one of many on SO) for why running long running tasks in ASP.NET is not always a good idea.
One option for the service is to use WCF. You can get started here. Your service could implement a method, say GetEvents() which you could use to pull your events. That way you won't tie up your page waiting for this process to complete (using AJAX of course). Also, this allows you to change your implementation of GetEvents() without touching your code on your website.

is there a better way to handle RPC_E_CALL_REJECTED exceptions when doing visual studio automation?

this is what I'm currently doing:
protected void setupProject()
{
bool lbDone = false;
int liCount = 0;
while (!lbDone && liCount < pMaxRetries)
{
try
{
pProject.ProjectItems.Item("Class1.cs").Delete();
lbDone = true;
}
catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001)
{
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
now I have that try catch block around most calls to the EnvDTE stuff, and it works well enough. The problem I have is when I to loop through a collection and do something to each item once.
foreach(ProjectItem pi in pProject.ProjectItems)
{
// do something to pi
}
Sometimes I get the exception in the foreach(ProjectItem pi in pProject.ProjectItems) line.
Since I don't want to start the foreach loop over if I get the RPC_E_CALL_REJECTED exception I'm not sure what I can do.
Edit to answer comment:
Yes I'm automating VS from another program and yes I usually am using VS for something else at the same time. We have an application that reads an xml file then generates around 50 VS solutions based on the xml file. This usually takes a couple of hours so I try to do other work while this is happening.
There is a solution on this MSDN page: How to: Fix 'Application is Busy' and 'Call was Rejected By Callee' Errors. It shows how to implement a COM IOleMessageFilter interface so that it will automatically retry the call.
First, Hans doesn't want to say so but the best answer to "how to do this" is "don't do this". Just use separate instances of visual studio for your automation and your other work, if at all possible.
You need to take your problem statement out somewhere you can handle the error. You can do this by using in integer index instead of foreach.
// You might also need try/catch for this!
int cProjectItems = pProject.ProjectItems.Length;
for(iProjectItem = 0; iProjectItem < cProjectItems; iProjectItem++)
{
bool bSucceeded = false;
while(!bSucceeded)
{
try{
ProjectItem pi = pProject.ProjectItems[iProjectItem];
// do something with pi
bSucceeded = true;
}catch (System.Runtime.InteropServices.COMException loE)
{
liCount++;
if ((uint)loE.ErrorCode == 0x80010001) {
// RPC_E_CALL_REJECTED - sleep half sec then try again
System.Threading.Thread.Sleep(pDelayBetweenRetry);
}
}
}
}
I didn't have much luck with the recommended way from MSDN, and it seemed rather complicated. What I have done is to wrap up the re-try logic, rather like in the original post, into a generic utility function. You call it like this:
Projects projects = Utils.call( () => (m_dteSolution.Projects) );
The 'call' function calls the function (passed in as a lambda expression) and will retry if necessary. Because it is a generic function, you can use it to call any EnvDTE properties or methods, and it will return the correct type.
Here's the code for the function:
public static T call<T>(Func<T> fn)
{
// We will try to call the function up to 100 times...
for (int i=0; i<100; ++i)
{
try
{
// We call the function passed in and return the result...
return fn();
}
catch (COMException)
{
// We've caught a COM exception, which is most likely
// a Server is Busy exception. So we sleep for a short
// while, and then try again...
Thread.Sleep(1);
}
}
throw new Exception("'call' failed to call function after 100 tries.");
}
As the original post says, foreach over EnvDTE collections can be a problem as there are implicit calls during the looping. So I use my 'call' function to get the Count proprty and then iterate using an index. It's uglier than foreach, but the 'call' function makes it not so bad, as there aren't so many try...catches around. For example:
int numProjects = Utils.call(() => (projects.Count));
for (int i = 1; i <= numProjects; ++i)
{
Project project = Utils.call(() => (projects.Item(i)));
parseProject(project);
}
I was getting the same error using C# to read/write to Excel. Oddly, it worked in debug mode but not on a deployed machine. I simply changed the Excel app to be Visible, and it works properly, albeit about twice as slow. It is annoying to have an Excel app open and close dynamically on your screen, but this seems to be the simplest work-around for Excel.
Microsoft.Office.Interop.Excel.Application oApp = new ApplicationClass();
oApp.Visible = true;
oApp.DisplayAlerts = false;

Categories