【发布时间】:2015-04-09 08:53:39
【问题描述】:
我在 Visual Studio 中遇到了一些奇怪的错误,找不到头部或尾部。我正在用 C# 编写一些后端,它联系第三方 API 来检索数据。有问题的代码,单个类,是更大解决方案的一部分,但必须是问题,因为不使用此类时不会发生遇到的错误。
电脑设置:
-
Visual Studio 2013,更新 4
-
Windows 10,预览版 10041
遇到的错误
昨天,应用程序在调试时开始表现得很奇怪。 第一个错误我记不太清了,但它类似于“坏”或“损坏的记忆”。
如果不修改程序,我也可能会遇到 FatalExecutionEngineError 异常,该异常会在尝试运行程序后立即抛出(它没有到达第一个断点,它位于 Main 条目的第一行程序。奇怪!
编辑:看起来像这样:
托管调试助手“FatalExecutionEngineError”检测到“PathRedacted\whatsfordinner\whatsfordinner\bin\Debug\whatsfordinner.vshost.exe”存在问题。
附加信息:运行时遇到致命错误。错误地址位于线程 0x11ac 上的 0x613e4379。错误代码为 0xc0000005。此错误可能是 CLR 中的错误或用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括 COM 互操作或 PInvoke 的用户封送错误,这可能会损坏堆栈。
最后我重新启动了我的电脑,因为这一切都很奇怪。问题解决到今天。
现在我似乎根本无法运行该程序;运行程序后,vshost32.exe 就崩溃了。我没有收到任何错误消息或任何提示问题所在的信息。
故障排除步骤
- 重新启动我的计算机 - 没有变化,vshost32.exe 在执行时崩溃
- 将使用相关类的两行注释掉 - 程序运行良好。
- 尝试以“Release”而不是“Debug”启动程序。 - 程序似乎运行良好,虽然我无法测试到最后。 (课程还没有完全完成,我不想向有问题的 API 发送垃圾邮件)
- 尝试在另一台运行 Windows 7 和 Visual Studio 2012 的计算机上运行该程序。- 程序似乎运行良好。
在这一点上,我很迷茫。我不知道问题可能出在哪里。不幸的是,源代码包含近 200 行,但由于我不知道,我将其全部发布。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Specialized;
using System.Net;
using System.IO;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
namespace whatsfordinner {
public class eTilbudRetriever {
//Web method names
readonly String Get = "GET";
readonly String Post = "POST";
readonly String Update = "UPDATE";
readonly String Delete = "DELETE";
//Parameter identifiers
readonly String ParamApiKey = "api_key";
readonly String ParamLatitude = "r_lat";
readonly String ParamLongitude = "r_lng";
readonly String ParamRadius = "r_radius";
readonly String ParamLimit = "limit";
readonly String ParamOffset = "offset";
//Parameter values
String Latitude = "57.051188"; //Aalborg coordinates
String Longitude = "9.922371";
String Radius = "800000"; //Radius in meters (800km)
String Limit = "48"; // Results per query
//Custom header identifiers
readonly String HeaderXToken = "X-Token";
readonly String HeaderXSignature = "X-Signature";
//Custom header values
readonly String ContentType = "application/json";
//Web Addresses
readonly String HostAddress = "https://api.etilbudsavis.dk/v2/";
readonly String Sessions = "sessions";
readonly String Stores = "stores";
readonly String Offers = "offers";
readonly String Dealers = "dealers";
//Keys
readonly String ApiKey = "<Redacted>";
readonly String ApiSecret = "<Redacted>";
String XToken; //Same as a Session Token in documentation
String XSignature; //Same as a Session Signature in documentation
public eTilbudRetriever() {
//Create a body consisting of the API key
List<KeyValuePair<String, String>> body = new List<KeyValuePair<String, String>>();
body.Add(new KeyValuePair<String, String>(ParamApiKey, ApiKey));
//Send request to create a new session
String response = SendWebRequest(Post, Sessions, body);
//Get the Session Token from the response
dynamic json = JObject.Parse(response);
XToken = json.token;
//Save the Session Signature as well (SHA256 version of API Secret combined with Session Token)
XSignature = ConvertToSha256(ApiSecret + XToken);
}
public void GetDealersList() {
GetList(Dealers);
}
public void GetStoresList() {
GetList(Stores);
}
public void GetOffersList() {
GetList(Offers);
}
private void GetList(string target) {
List<String> resultSet = new List<String>();
String result;
int offset = 0;
//Add desired parameters as headers for the eTilbudsavisen API
List<KeyValuePair<String, String>> query = new List<KeyValuePair<String, String>>();
query.Add(new KeyValuePair<String, String>(ParamLatitude, Latitude));
query.Add(new KeyValuePair<String, String>(ParamLongitude, Longitude));
query.Add(new KeyValuePair<String, String>(ParamRadius, Radius));
query.Add(new KeyValuePair<String, String>(ParamLimit, Limit));
query.Add(new KeyValuePair<String, String>(ParamOffset, offset.ToString()));
//Retrieve a result through the request
result = SendWebRequest(Get, target, query);
/*
* If result is valid, add it to the set of valid results.
* Keep sending requests and increase the offset to avoid duplicated results
* Stop when returned results are no longer valid
*/
while (!String.IsNullOrEmpty(result)) {
resultSet.Add(result);
offset += Int32.Parse(Limit);
query[query.Count-1] = new KeyValuePair<String, String>(ParamOffset, offset.ToString());
result = SendWebRequest(Get, target, query);
}
}
private String SendWebRequest(String method, String extension, List<KeyValuePair<String, String>> arguments) {
try {
String finalAddress = HostAddress + extension;
//Add query to Address (if applicable)
if (method.Equals(Get)) {
finalAddress += '?';
finalAddress += arguments[0].Key + '=' + arguments[0].Value;
for (int i = 1; i < arguments.Count; i++) {
finalAddress += '&' + arguments[i].Key + '=' + arguments[i].Value;
}
}
//Create request and set mandatory header properties
var request = (HttpWebRequest)WebRequest.Create(finalAddress);
request.Method = method;
request.ContentType = ContentType;
request.Accept = ContentType;
//If a Session Token and Signature are available (= After session create), add as headers
if (!String.IsNullOrEmpty(XToken)) {
request.Headers.Add(HeaderXToken, XToken);
request.Headers.Add(HeaderXSignature, XSignature);
}
//Create JSON string containing the desired body arguments (if applicable)
if (method.Equals(Post)) {
//Write body to API
using (var writer = new StreamWriter(request.GetRequestStream())) {
writer.Write(MakeJsonBody(arguments));
}
}
//get response as a JSON object in string format
var response = (HttpWebResponse)request.GetResponse();
return new StreamReader(response.GetResponseStream()).ReadToEnd();
} catch (UriFormatException e) {
Console.WriteLine(e.ToString());
return null;
} catch (WebException e) {
Console.WriteLine(e.ToString());
return null;
}
}
private String ConvertToSha256(String text) {
byte[] bytes = Encoding.UTF8.GetBytes(text);
SHA256Managed hashstring = new SHA256Managed();
byte[] hash = hashstring.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash) {
hashString += String.Format("{0:x2}", x);
}
return hashString;
}
private String MakeJsonBody(List<KeyValuePair<String, String>> arguments) {
String json = "{";
foreach (KeyValuePair<String, String> kv in arguments) {
json += "\"" + kv.Key + "\": \"" + kv.Value + "\"";
if (arguments.IndexOf(kv) != arguments.Count() - 1) {
json += ", ";
}
}
json += "}";
return json;
}
}
}
在Main 中,这是与类相关的执行内容。从解决方案中删除这些行时,程序运行良好。
eTilbudRetriever retriever = new eTilbudRetriever();
retriever.GetDealersList();
【问题讨论】:
-
请将您的 { 换行。也许将它限制在前一行是 javascript 中的约定。但这真的很糟糕,因为将它们与他们的 } 匹配变得更加困难
-
你现在是认真的吗?这是个人喜好问题。
-
是否不好是偏好,但这不是 C# 中的约定。您发现在不同的水平位置上匹配牙套很容易吗?我发现你的代码比需要的更难阅读。
-
它是 Visual Studio 提供的一个选项。我发现当起始大括号与它们所属的代码在同一行时,代码更容易阅读。我真的不想要一整行的大括号来查看某事从哪里开始。你有什么关于这个话题的吗?我还没有找到解决方案,目前正在使用另一台计算机对我的项目的这一部分进行编程。
标签: c# exception visual-studio-2013 crash httpwebrequest